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 +4 -4
- data/Gemfile.lock +3 -1
- data/app/components/avo/base_component.rb +28 -0
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +1 -1
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +10 -2
- data/app/components/avo/index/ordering/base_component.rb +1 -1
- data/app/components/avo/index/ordering/button_component.html.erb +1 -0
- data/app/components/avo/index/ordering/button_component.rb +11 -5
- data/app/components/avo/index/ordering/buttons_component.html.erb +14 -12
- data/app/components/avo/index/ordering/buttons_component.rb +30 -4
- data/app/components/avo/index/resource_controls_component.html.erb +1 -3
- data/app/components/avo/index/resource_controls_component.rb +0 -4
- data/app/components/avo/resource_component.rb +0 -21
- data/app/controllers/avo/base_controller.rb +5 -3
- data/app/controllers/avo/relations_controller.rb +29 -12
- data/app/helpers/avo/url_helpers.rb +6 -2
- data/app/views/avo/partials/_profile_dropdown.html.erb +1 -1
- data/app/views/avo/relations/new.html.erb +15 -12
- data/avo.gemspec +1 -0
- data/config/routes.rb +1 -0
- data/lib/avo/base_resource.rb +15 -6
- data/lib/avo/fields/base_field.rb +1 -1
- data/lib/avo/fields/belongs_to_field.rb +1 -1
- data/lib/avo/fields/date_field.rb +1 -1
- data/lib/avo/fields/has_base_field.rb +24 -1
- data/lib/avo/hosts/ordering.rb +22 -0
- data/lib/avo/licensing/pro_license.rb +2 -2
- data/lib/avo/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbaf39a3e7e7d5bd9ed2e5fc7f61cdacf70387c5f943c8ccc4405378c67dd6a7
|
4
|
+
data.tar.gz: 97359bfa2572ad00f84b3cf21582406eaa0bf3205a61ef503f02d4a15e234c39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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 @
|
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
|
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
|
-
|
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,12 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::Index::Ordering::ButtonComponent < Avo::Index::Ordering::BaseComponent
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
attr_accessor :resource
|
5
|
+
attr_accessor :reflection
|
6
|
+
attr_accessor :direction
|
7
|
+
attr_accessor :svg
|
7
8
|
|
8
|
-
def initialize(resource
|
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
|
-
|
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
|
-
<%
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
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
|
17
|
-
@
|
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
|
-
|
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?
|
198
|
-
|
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
|
-
|
37
|
+
@resource.hydrate(model: @model)
|
38
38
|
|
39
|
-
|
40
|
-
|
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: @
|
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
|
-
#
|
16
|
-
|
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(
|
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:
|
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
|
-
|
14
|
-
<%=
|
15
|
-
|
16
|
-
|
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
|
-
|
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
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"
|
data/lib/avo/base_resource.rb
CHANGED
@@ -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
|
-
|
146
|
-
|
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
|
-
|
153
|
-
|
154
|
-
|
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->
|
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:
|
10
|
+
delegate :view_context, to: "Avo::App"
|
11
11
|
delegate :main_app, to: :view_context
|
12
12
|
delegate :avo, to: :view_context
|
13
13
|
|
@@ -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
|
data/lib/avo/version.rb
CHANGED
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.
|
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-
|
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
|