avo 1.24.1 → 1.25.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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07dcdf41c01ae279e2cfcd9df2cfcafa425631eb55f62683cd3840265d940929
4
- data.tar.gz: 138598c44f46114939d9c6e0aa3a7cc2b07c36a4c6a4bf4092371fed1304a610
3
+ metadata.gz: fbaf39a3e7e7d5bd9ed2e5fc7f61cdacf70387c5f943c8ccc4405378c67dd6a7
4
+ data.tar.gz: 97359bfa2572ad00f84b3cf21582406eaa0bf3205a61ef503f02d4a15e234c39
5
5
  SHA512:
6
- metadata.gz: e76cb0cd3f45b95f5415f68eb467a9bdb65a254b78c2a1e60803903a0b2a52f34b1b1872be770443c4c9505b3dfab0bb526688867a9c6efc8eae2904a0fc9cd1
7
- data.tar.gz: df4ca3e819a13d3a1730f426b14625ab582fdc9460afa1d3bde5b200fe63e9573fa976e9a5d961318357317149aa5dc3b9127673e661ca0cc1532fb0e1d000de
6
+ metadata.gz: 9aa49a22c165ca4ec0638603e1fdda8649ca612b99e847fa015e20edf81b64527d408e47e2af19d0cac3b8fb5389e5608423305334090918c2cb6ff382d37634
7
+ data.tar.gz: c79b94df66a4910bddd53d7fa2a3a4c2a904919e4781a30e82053b8ff65559b48eef0d778f561ac11c845f461bf544d205c193168d7b890365490518f419788b
data/Gemfile.lock CHANGED
@@ -1,11 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (1.24.1)
4
+ avo (1.25.1)
5
5
  active_link_to
6
6
  addressable
7
7
  breadcrumbs_on_rails
8
8
  countries
9
+ dry-initializer
9
10
  hotwire-rails
10
11
  httparty
11
12
  image_processing
@@ -155,6 +156,7 @@ GEM
155
156
  dotenv-rails (2.7.6)
156
157
  dotenv (= 2.7.6)
157
158
  railties (>= 3.2)
159
+ dry-initializer (3.1.1)
158
160
  erubi (1.10.0)
159
161
  factory_bot (6.2.0)
160
162
  activesupport (>= 5.0.0)
@@ -4,4 +4,32 @@ class Avo::BaseComponent < ViewComponent::Base
4
4
  def has_with_trial(ability)
5
5
  ::Avo::App.license.has_with_trial(ability)
6
6
  end
7
+
8
+ private
9
+
10
+ # Figure out what is the corresponding field for this @reflection
11
+ def field
12
+ fields = ::Avo::App.get_resource_by_model_name(@reflection.active_record.name).get_field_definitions
13
+ fields.find { |f| f.id == @reflection.name }
14
+ rescue
15
+ nil
16
+ end
17
+
18
+ def relation_resource
19
+ ::Avo::App.get_resource_by_model_name params[:via_resource_class].safe_constantize
20
+ end
21
+
22
+ # Get the resource for the resource using the klass attribute so we get the namespace too
23
+ def reflection_resource
24
+ ::Avo::App.get_resource_by_model_name(@reflection.klass.to_s)
25
+ rescue
26
+ nil
27
+ end
28
+
29
+ # Get the resource for the resource using the klass attribute so we get the namespace too
30
+ def reflection_parent_resource
31
+ ::Avo::App.get_resource_by_model_name(@reflection.active_record.to_s)
32
+ rescue
33
+ nil
34
+ end
7
35
  end
@@ -6,7 +6,7 @@
6
6
  data-via-association="belongs_to"
7
7
  ></div>
8
8
  <div class="relative w-full" autocomplete="off">
9
- <%= @form.text_field @field.foreign_key,
9
+ <%= @form.text_field @foreign_key,
10
10
  value: field_label,
11
11
  class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
12
12
  placeholder: @field.placeholder,
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Fields::BelongsToField::AutocompleteComponent < ViewComponent::Base
4
- def initialize(form:, field:, model_key:, foreign_key:, disabled:, type: nil, resource: nil, polymorphic_record: nil)
4
+ def initialize(form:, field:, model_key:, foreign_key:, disabled: false, type: nil, resource: nil, polymorphic_record: nil)
5
5
  @form = form
6
6
  @field = field
7
7
  @type = type
@@ -37,7 +37,15 @@ class Avo::Fields::BelongsToField::AutocompleteComponent < ViewComponent::Base
37
37
  private
38
38
 
39
39
  def should_prefill?
40
- @field.is_polymorphic? && searchable? && !(new_record? && has_polymorphic_association?)
40
+ # default this conditional to true
41
+ is_polymorphic = true
42
+
43
+ # if this is a field that can be polymorphic (belongs_to)
44
+ if @field.respond_to? :is_polymorphic?
45
+ is_polymorphic = @field.is_polymorphic?
46
+ end
47
+
48
+ is_polymorphic && searchable? && !(new_record? && has_polymorphic_association?)
41
49
  end
42
50
 
43
51
  def searchable?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Avo::Index::Ordering::BaseComponent < ViewComponent::Base
3
+ class Avo::Index::Ordering::BaseComponent < Avo::BaseComponent
4
4
  private
5
5
 
6
6
  def order_actions
@@ -4,6 +4,7 @@
4
4
  class: 'flex items-center',
5
5
  data: {
6
6
  target: "order:#{direction}",
7
+ 'turbo-frame': params[:turbo_frame],
7
8
  'tippy': 'tooltip',
8
9
  } do %>
9
10
  <%= helpers.svg(svg, class: 'text-gray-400 h-6 hover:text-gray-600') %>
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Index::Ordering::ButtonComponent < Avo::Index::Ordering::BaseComponent
4
- attr_reader :resource
5
- attr_reader :direction
6
- attr_reader :svg
4
+ attr_accessor :resource
5
+ attr_accessor :reflection
6
+ attr_accessor :direction
7
+ attr_accessor :svg
7
8
 
8
- def initialize(resource: nil, direction: nil, svg: nil)
9
+ def initialize(resource:, direction:, svg: nil, reflection: nil)
9
10
  @resource = resource
11
+ @reflection = reflection
10
12
  @direction = direction
11
13
  @svg = svg
12
14
  end
@@ -16,7 +18,11 @@ class Avo::Index::Ordering::ButtonComponent < Avo::Index::Ordering::BaseComponen
16
18
  end
17
19
 
18
20
  def order_path(args)
19
- path = "#{::Avo::App.root_path}/resources/#{resource.route_key}/#{resource.model.id}/order"
21
+ if reflection.present?
22
+ path = "#{::Avo::App.root_path}/resources/#{reflection_parent_resource.route_key}/#{params[:id]}/#{field.id}/#{resource.model.id}/order"
23
+ else
24
+ path = "#{::Avo::App.root_path}/resources/#{resource.route_key}/#{resource.model.id}/order"
25
+ end
20
26
 
21
27
  if args.present?
22
28
  string_args = args.map do |key, value|
@@ -1,5 +1,12 @@
1
1
  <div class="flex items-center justify-center">
2
- <% unless always_visible? %>
2
+ <% if display_inline? %>
3
+ <div class="flex max-w-xs rounded">
4
+ <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :higher, svg: 'arrow-up' %>
5
+ <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :lower, svg: 'arrow-down' %>
6
+ <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :to_top, svg: 'download-solid-reversed' %>
7
+ <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :to_bottom, svg: 'download-solid' %>
8
+ </div>
9
+ <% else %>
3
10
  <div class="popover inline-block"
4
11
  data-controller="popover"
5
12
  data-popover-translate-x="-100%"
@@ -15,16 +22,11 @@
15
22
  %>
16
23
  <%= helpers.svg('switch-vertical', class: 'text-gray-400 h-6 hover:text-gray-600') %>
17
24
  <% end %>
18
- <% end %>
19
- <% if always_visible? %>
20
- <div class="flex max-w-xs rounded">
21
- <% else %>
22
- <div class="flex hidden absolute max-w-xs bg-white rounded p-2 z-40" data-popover-target="content">
23
- <% end %>
24
- <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, direction: :higher, svg: 'arrow-up' %>
25
- <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, direction: :lower, svg: 'arrow-down' %>
26
- <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, direction: :to_top, svg: 'download-solid-reversed' %>
27
- <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, direction: :to_bottom, svg: 'download-solid' %>
25
+ <div class="flex hidden absolute max-w-xs bg-white rounded p-2 z-40" data-popover-target="content">
26
+ <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :higher, svg: 'arrow-up' %>
27
+ <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :lower, svg: 'arrow-down' %>
28
+ <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :to_top, svg: 'download-solid-reversed' %>
29
+ <%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :to_bottom, svg: 'download-solid' %>
28
30
  </div>
29
- </div>
31
+ <% end %>
30
32
  </div>
@@ -1,19 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Index::Ordering::ButtonsComponent < Avo::Index::Ordering::BaseComponent
4
- def initialize(resource: nil)
4
+ def initialize(resource: nil, reflection: nil, view_type: nil)
5
5
  @resource = resource
6
+ @reflection = reflection
7
+ @view_type = view_type
6
8
  end
7
9
 
8
10
  def render?
9
- can_order_any?
11
+ has_with_trial(:resource_ordering) && can_order_any? && view_type_is_table? && enabled_in_view?
10
12
  end
11
13
 
14
+ private
15
+
12
16
  def can_order_any?
13
17
  order_actions.present?
14
18
  end
15
19
 
16
- def always_visible?
17
- @resource.class.ordering[:always_visible]
20
+ def view_type_is_table?
21
+ @view_type.to_sym == :table
22
+ end
23
+
24
+ def display_inline?
25
+ ordering[:display_inline]
26
+ end
27
+
28
+ def enabled_in_view?
29
+ in_association = @reflection.present?
30
+
31
+ if in_association
32
+ visible_on_option.include? :association
33
+ else
34
+ visible_on_option.include? :index
35
+ end
36
+ end
37
+
38
+ def visible_on_option
39
+ [ordering[:visible_on]].flatten
40
+ end
41
+
42
+ def ordering
43
+ @resource.class.ordering
18
44
  end
19
45
  end
@@ -1,7 +1,5 @@
1
1
  <div class="space-x-2 flex flex-row justify-around items-center w-full">
2
- <% if view_is_table? && has_with_trial(:resource_ordering) %>
3
- <%= render Avo::Index::Ordering::ButtonsComponent.new resource: @resource %>
4
- <% end %>
2
+ <%= render Avo::Index::Ordering::ButtonsComponent.new resource: @resource, reflection: @reflection, view_type: @view_type %>
5
3
 
6
4
  <% if can_view? %>
7
5
  <%= link_to helpers.svg('eye', class: 'text-gray-400 h-6 hover:text-gray-600'),
@@ -70,8 +70,4 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
70
70
  def is_has_many_association
71
71
  @reflection.is_a?(::ActiveRecord::Reflection::HasManyReflection) || @reflection.is_a?(::ActiveRecord::Reflection::ThroughReflection)
72
72
  end
73
-
74
- def view_is_table?
75
- @view_type == :table
76
- end
77
73
  end
@@ -30,25 +30,4 @@ class Avo::ResourceComponent < Avo::BaseComponent
30
30
 
31
31
  association_policy
32
32
  end
33
-
34
- private
35
-
36
- # Figure out what is the corresponding field for this @reflection
37
- def field
38
- fields = ::Avo::App.get_resource_by_model_name(@reflection.active_record.name).get_field_definitions
39
- fields.find { |f| f.id == @reflection.name }
40
- rescue
41
- nil
42
- end
43
-
44
- def relation_resource
45
- ::Avo::App.get_resource_by_model_name params[:via_resource_class].safe_constantize
46
- end
47
-
48
- # Get the resource for the resource using the klass attribute so we get the namespace too
49
- def reflection_resource
50
- ::Avo::App.get_resource_by_model_name(@reflection.klass.to_s)
51
- rescue
52
- nil
53
- end
54
33
  end
@@ -192,10 +192,12 @@ module Avo
192
192
 
193
193
  def order
194
194
  direction = params[:direction].to_sym
195
- order_actions = @resource.class.order_actions
196
195
 
197
- if direction.present? && order_actions[direction].present?
198
- order_actions[direction].call(@model)
196
+ if direction.present?
197
+ @resource
198
+ .hydrate(model: @model, params: params)
199
+ .ordering_host
200
+ .order direction
199
201
  end
200
202
 
201
203
  respond_to do |format|
@@ -2,15 +2,15 @@ require_dependency "avo/base_controller"
2
2
 
3
3
  module Avo
4
4
  class RelationsController < BaseController
5
- before_action :set_model, only: [:show, :index, :new, :create, :destroy]
5
+ before_action :set_model, only: [:show, :index, :new, :create, :destroy, :order]
6
6
  before_action :set_related_resource_name
7
- before_action :set_related_resource, only: [:show, :index, :new, :create, :destroy]
8
- before_action :hydrate_related_resource, only: [:show, :index, :new, :create, :destroy]
9
- before_action :set_related_model, only: [:show]
10
- before_action :set_attachment_class, only: [:show, :index, :new, :create, :destroy]
11
- before_action :set_attachment_resource, only: [:show, :index, :new, :create, :destroy]
12
- before_action :set_attachment_model, only: [:create, :destroy]
13
- before_action :set_reflection, only: [:index, :show]
7
+ before_action :set_related_resource, only: [:show, :index, :new, :create, :destroy, :order]
8
+ before_action :hydrate_related_resource, only: [:show, :index, :new, :create, :destroy, :order]
9
+ before_action :set_related_model, only: [:show, :order]
10
+ before_action :set_attachment_class, only: [:show, :index, :new, :create, :destroy, :order]
11
+ before_action :set_attachment_resource, only: [:show, :index, :new, :create, :destroy, :order]
12
+ before_action :set_attachment_model, only: [:create, :destroy, :order]
13
+ before_action :set_reflection, only: [:index, :show, :order]
14
14
 
15
15
  def index
16
16
  @parent_resource = @resource.dup
@@ -34,10 +34,20 @@ module Avo
34
34
  end
35
35
 
36
36
  def new
37
- query = @authorization.apply_policy @attachment_class
37
+ @resource.hydrate(model: @model)
38
38
 
39
- @options = query.all.map do |model|
40
- [model.send(@attachment_resource.class.title), model.id]
39
+ begin
40
+ @field = @resource.get_field_definitions.find { |f| f.id == @related_resource_name.to_sym }
41
+ @field.hydrate(resource: @resource, model: @model, view: :new)
42
+ rescue
43
+ end
44
+
45
+ if @field.present? && !@field.searchable
46
+ query = @authorization.apply_policy @attachment_class
47
+
48
+ @options = query.all.map do |model|
49
+ [model.send(@attachment_resource.class.title), model.id]
50
+ end
41
51
  end
42
52
  end
43
53
 
@@ -50,7 +60,7 @@ module Avo
50
60
 
51
61
  respond_to do |format|
52
62
  if @model.save
53
- format.html { redirect_to resource_path(model: @model, resource: @resource), notice: t("avo.attachment_class_attached", attachment_class: @attachment_class) }
63
+ format.html { redirect_to resource_path(model: @model, resource: @resource), notice: t("avo.attachment_class_attached", attachment_class: @related_resource.name) }
54
64
  format.json { render :show, status: :created, location: resource_path(model: @model, resource: @resource) }
55
65
  else
56
66
  format.html { render :new }
@@ -71,6 +81,13 @@ module Avo
71
81
  end
72
82
  end
73
83
 
84
+ def order
85
+ @parent_resource = @resource.dup
86
+ @resource, @model = @related_resource, @related_model
87
+
88
+ super
89
+ end
90
+
74
91
  private
75
92
 
76
93
  def set_attachment_class
@@ -12,8 +12,12 @@ module Avo
12
12
  rescue
13
13
  end
14
14
 
15
- # This entry uses `route_key` instead of `model_key` because it's rails that needs `fish_index` to build the correct path
16
- avo.send :"resources_#{resource.route_key}_path", **existing_params, **args
15
+ # Create the `route_key` from the model key so the namespaced models get the proper path (SomeModule::Post -> some_module_post).
16
+ # Add the `_index` suffix for the uncountable models so they get the correct path (`fish_index`)
17
+ route_key = resource.model_key
18
+ route_key << "_index" if resource.model_name.singular == resource.model_name.plural
19
+
20
+ avo.send :"resources_#{route_key}_path", **existing_params, **args
17
21
  end
18
22
 
19
23
  def resource_path(
@@ -19,7 +19,7 @@
19
19
 
20
20
  <% if main_app.respond_to?(destroy_user_session_path) %>
21
21
  <div class="hidden absolute inset-auto right-0 mr-6 mt-0 py-4 bg-white rounded-xl min-w-[200px] shadow-context" data-toggle-panel-target="panel">
22
- <%= button_to t('avo.sign_out'), main_app.send(:destroy_user_session_path), method: :delete, form: { "data-turbo" => "false" }, class: "appearance-none bg-white text-left cursor-pointer text-green-600 font-semibold hover:text-white hover:bg-green-500 block px-4 py-1 w-full" %>
22
+ <%= button_to t('avo.sign_out'), main_app.send(destroy_user_session_path), method: :delete, form: { "data-turbo" => "false" }, class: "appearance-none bg-white text-left cursor-pointer text-green-600 font-semibold hover:text-white hover:bg-green-500 block px-4 py-1 w-full" %>
23
23
  </div>
24
24
  <% end %>
25
25
  </div>
@@ -6,22 +6,25 @@
6
6
  } do |form| %>
7
7
  <%= render Avo::ModalComponent.new do |c| %>
8
8
  <% c.heading do %>
9
- <%= t 'avo.choose_item', item: params[:related_name].downcase %>
9
+ <%= t 'avo.choose_item', item: @related_resource.name.downcase %>
10
10
  <% end %>
11
-
12
11
  <div class="flex-1 flex items-center justify-center px-8 text-lg mt-8 mb-12">
13
- <div class="flex-1 flex flex-col items-center justify-center px-24 text-base">
14
- <%= form.select :related_id, options_for_select(@options, nil),
15
- {
16
- include_blank: t('avo.choose_an_option'),
17
- },
18
- {
19
- class: input_classes('w-full'),
20
- }
12
+ <% if @field.searchable %>
13
+ <%= render Avo::Fields::BelongsToField::AutocompleteComponent.new form: form,
14
+ field: @field,
15
+ model_key: @field.target_resource&.model_key,
16
+ foreign_key: 'related_id',
17
+ resource: @resource
21
18
  %>
22
- </div>
19
+ <% else %>
20
+ <div class="flex-1 flex flex-col items-center justify-center px-24 text-base">
21
+ <%= form.select :related_id, options_for_select(@options, nil),
22
+ { include_blank: t('avo.choose_an_option') },
23
+ { class: input_classes('w-full') }
24
+ %>
25
+ </div>
26
+ <% end %>
23
27
  </div>
24
-
25
28
  <% c.controls do %>
26
29
  <%= a_button t('avo.cancel'), 'data-action': 'click->modal#close', size: :sm %>
27
30
  <%= a_button t('avo.attach'), type: :submit, color: :green, size: :sm %>
data/avo.gemspec CHANGED
@@ -44,4 +44,5 @@ Gem::Specification.new do |spec|
44
44
  spec.add_dependency "addressable"
45
45
  spec.add_dependency "meta-tags"
46
46
  spec.add_dependency "breadcrumbs_on_rails"
47
+ spec.add_dependency "dry-initializer"
47
48
  end
data/config/routes.rb CHANGED
@@ -19,6 +19,7 @@ Avo::Engine.routes.draw do
19
19
 
20
20
  # Ordering
21
21
  patch "/:resource_name/:id/order", to: "resources#order"
22
+ patch "/:resource_name/:id/:related_name/:related_id/order", to: "relations#order", as: "associations_order"
22
23
 
23
24
  # Actions
24
25
  get "/:resource_name(/:id)/actions/:action_id", to: "actions#show"
@@ -14,6 +14,7 @@ module Avo
14
14
 
15
15
  attr_accessor :view
16
16
  attr_accessor :model
17
+ attr_accessor :reflection
17
18
  attr_accessor :user
18
19
  attr_accessor :params
19
20
 
@@ -142,16 +143,16 @@ module Avo
142
143
  # we're matching the reflection inverse_of foriegn key with the field's foreign_key
143
144
  if field.is_a?(Avo::Fields::BelongsToField)
144
145
  if field.respond_to?(:foreign_key) &&
145
- reflection.inverse_of.present? &&
146
- reflection.inverse_of.foreign_key == field.foreign_key
146
+ reflection.inverse_of.present? &&
147
+ reflection.inverse_of.foreign_key == field.foreign_key
147
148
  is_valid = false
148
149
  end
149
150
 
150
151
  # polymorphic association
151
152
  if field.respond_to?(:foreign_key) &&
152
- field.is_polymorphic? &&
153
- reflection.respond_to?(:polymorphic?) &&
154
- reflection.inverse_of.foreign_key == field.reflection.foreign_key
153
+ field.is_polymorphic? &&
154
+ reflection.respond_to?(:polymorphic?) &&
155
+ reflection.inverse_of.foreign_key == field.reflection.foreign_key
155
156
  is_valid = false
156
157
  end
157
158
  end
@@ -405,11 +406,15 @@ module Avo
405
406
  # This is used as the model class ID
406
407
  # We use this instead of the route_key to maintain compatibility with uncountable models
407
408
  # With uncountable models route key appends an _index suffix (Fish->fish_index)
408
- # Example: User->users, MediaItem->medie_items, Fish->fish
409
+ # Example: User->users, MediaItem->media_items, Fish->fish
409
410
  def model_key
410
411
  model_class.model_name.plural
411
412
  end
412
413
 
414
+ def model_name
415
+ model_class.model_name
416
+ end
417
+
413
418
  def singular_model_key
414
419
  model_class.model_name.singular
415
420
  end
@@ -477,5 +482,9 @@ module Avo
477
482
  def form_scope
478
483
  model_class.base_class.to_s.underscore.downcase
479
484
  end
485
+
486
+ def ordering_host(**args)
487
+ Avo::Hosts::Ordering.new resource: self, options: self.class.ordering, **args
488
+ end
480
489
  end
481
490
  end
@@ -7,7 +7,7 @@ module Avo
7
7
  include ActionView::Helpers::UrlHelper
8
8
  include Avo::Fields::FieldExtensions::VisibleInDifferentViews
9
9
 
10
- delegate :view_context, to: 'Avo::App'
10
+ delegate :view_context, to: "Avo::App"
11
11
  delegate :main_app, to: :view_context
12
12
  delegate :avo, to: :view_context
13
13
 
@@ -74,7 +74,7 @@ module Avo
74
74
  end
75
75
 
76
76
  def searchable
77
- @searchable && ::Avo::App.license.has_with_trial(:searchable_belongs_to)
77
+ @searchable && ::Avo::App.license.has_with_trial(:searchable_associations)
78
78
  end
79
79
 
80
80
  def value
@@ -19,7 +19,7 @@ module Avo
19
19
  return if value.blank?
20
20
 
21
21
  if @format.is_a?(Symbol)
22
- value.to_s(@format)
22
+ value.to_formatted_s(@format)
23
23
  else
24
24
  value.strftime(@format)
25
25
  end
@@ -7,8 +7,13 @@ module Avo
7
7
  def initialize(id, **args, &block)
8
8
  super(id, **args, &block)
9
9
 
10
- @display = args[:display].present? ? args[:display] : :show
11
10
  @scope = args[:scope].present? ? args[:scope] : nil
11
+ @display = args[:display].present? ? args[:display] : :show
12
+ @searchable = args[:searchable] == true
13
+ end
14
+
15
+ def searchable
16
+ @searchable && ::Avo::App.license.has_with_trial(:searchable_associations)
12
17
  end
13
18
 
14
19
  def resource
@@ -23,6 +28,20 @@ module Avo
23
28
  "#{@resource.record_path}/#{id}?turbo_frame=#{turbo_frame}"
24
29
  end
25
30
 
31
+ # The value
32
+ def field_value
33
+ value.send(database_value)
34
+ rescue
35
+ nil
36
+ end
37
+
38
+ # What the user sees in the text field
39
+ def field_label
40
+ value.send(target_resource.class.title)
41
+ rescue
42
+ nil
43
+ end
44
+
26
45
  def target_resource
27
46
  if @model._reflections[id.to_s].klass.present?
28
47
  Avo::App.get_resource_by_model_name @model._reflections[id.to_s].klass.to_s
@@ -32,6 +51,10 @@ module Avo
32
51
  Avo::App.get_resource_by_name id.to_s
33
52
  end
34
53
  end
54
+
55
+ def placeholder
56
+ @placeholder || I18n.t("avo.choose_an_option")
57
+ end
35
58
  end
36
59
  end
37
60
  end
@@ -0,0 +1,22 @@
1
+ require 'dry-initializer'
2
+
3
+ module Avo
4
+ module Hosts
5
+ class Ordering
6
+ extend Dry::Initializer
7
+
8
+ option :options, default: proc { {} }
9
+ option :resource
10
+ option :record, default: proc { resource.model }
11
+ option :params, default: proc { resource.params }
12
+
13
+ def order(direction)
14
+ action = options.dig(:actions, direction.to_sym)
15
+
16
+ if action.present?
17
+ instance_exec(&action)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -8,8 +8,8 @@ module Avo
8
8
  :custom_fields,
9
9
  :global_search,
10
10
  :enhanced_search_results,
11
- :searchable_belongs_to,
12
- :resource_ordering,
11
+ :searchable_associations,
12
+ :resource_ordering
13
13
  ]
14
14
  end
15
15
  end
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "1.24.1"
2
+ VERSION = "1.25.1"
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: 1.24.1
4
+ version: 1.25.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: 2022-03-03 00:00:00.000000000 Z
12
+ date: 2022-04-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -193,6 +193,20 @@ dependencies:
193
193
  - - ">="
194
194
  - !ruby/object:Gem::Version
195
195
  version: '0'
196
+ - !ruby/object:Gem::Dependency
197
+ name: dry-initializer
198
+ requirement: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ type: :runtime
204
+ prerelease: false
205
+ version_requirements: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - ">="
208
+ - !ruby/object:Gem::Version
209
+ version: '0'
196
210
  description: Avo is a beautiful next-generation framework that empowers you, the developer,
197
211
  to create fantastic admin panels for your Ruby on Rails apps with the flexibility
198
212
  to fit your needs as you grow.
@@ -644,6 +658,7 @@ files:
644
658
  - lib/avo/grid_fields/preview_field.rb
645
659
  - lib/avo/grid_fields/title_field.rb
646
660
  - lib/avo/has_context.rb
661
+ - lib/avo/hosts/ordering.rb
647
662
  - lib/avo/licensing/community_license.rb
648
663
  - lib/avo/licensing/h_q.rb
649
664
  - lib/avo/licensing/license.rb