avo 1.24.2 → 1.25.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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +4 -4
- 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/controllers/avo/relations_controller.rb +14 -4
- data/app/views/avo/relations/new.html.erb +15 -12
- data/lib/avo/base_resource.rb +5 -5
- data/lib/avo/fields/base_field.rb +1 -1
- data/lib/avo/fields/belongs_to_field.rb +1 -1
- data/lib/avo/fields/has_base_field.rb +24 -1
- data/lib/avo/licensing/pro_license.rb +2 -2
- data/lib/avo/version.rb +1 -1
- data/public/avo-assets/avo.js +7 -5
- data/public/avo-assets/avo.js.map +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 371a5db5091d8aad3fd0109c8640a06b10ee5cb61d9b16c5a98d25e566b54787
|
4
|
+
data.tar.gz: 8c15d927349aed0e15ccda76f656883e51ca8c3d33ba703c2646ff7a59695a1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab631914363eb8bd77a5f1053d9c568d6e36f2cdd8c05a84845e4726e3d069394afc1be9778dcc3ad051a91839cb1ef050b12711e165cf8140014cb844096c8c
|
7
|
+
data.tar.gz: 8cbbe3db1bd3e0b77b548706eb696f0ee0bb455cdb2d5ccab6047e4747a0eeae9eff167456bd214ab392825b6c356d061be07c15c7732ef213bc4fa64753c3df
|
data/Gemfile
CHANGED
@@ -39,7 +39,7 @@ gem "puma", "~> 5.6.2"
|
|
39
39
|
# gem 'bcrypt', '~> 3.1.7'
|
40
40
|
|
41
41
|
# Use Active Storage variant
|
42
|
-
gem "image_processing", "~> 1.
|
42
|
+
gem "image_processing", "~> 1.12"
|
43
43
|
|
44
44
|
# Reduces boot times through caching; required in config/boot.rb
|
45
45
|
gem "bootsnap", ">= 1.4.2", require: false
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (1.
|
4
|
+
avo (1.25.0)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
@@ -187,7 +187,7 @@ GEM
|
|
187
187
|
concurrent-ruby (~> 1.0)
|
188
188
|
i18n_data (0.15.0)
|
189
189
|
simple_po_parser (~> 1.1)
|
190
|
-
image_processing (1.12.
|
190
|
+
image_processing (1.12.2)
|
191
191
|
mini_magick (>= 4.9.5, < 5)
|
192
192
|
ruby-vips (>= 2.0.17, < 3)
|
193
193
|
io-wait (0.2.1)
|
@@ -370,7 +370,7 @@ GEM
|
|
370
370
|
tzinfo (2.0.4)
|
371
371
|
concurrent-ruby (~> 1.0)
|
372
372
|
unicode-display_width (2.1.0)
|
373
|
-
view_component (2.
|
373
|
+
view_component (2.49.1)
|
374
374
|
activesupport (>= 5.0.0, < 8.0)
|
375
375
|
method_source (~> 1.0)
|
376
376
|
warden (1.2.9)
|
@@ -425,7 +425,7 @@ DEPENDENCIES
|
|
425
425
|
hotwire-rails
|
426
426
|
htmlbeautifier
|
427
427
|
httparty
|
428
|
-
image_processing (~> 1.
|
428
|
+
image_processing (~> 1.12)
|
429
429
|
iso
|
430
430
|
jsbundling-rails
|
431
431
|
launchy
|
@@ -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?
|
@@ -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 }
|
@@ -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/lib/avo/base_resource.rb
CHANGED
@@ -143,16 +143,16 @@ module Avo
|
|
143
143
|
# we're matching the reflection inverse_of foriegn key with the field's foreign_key
|
144
144
|
if field.is_a?(Avo::Fields::BelongsToField)
|
145
145
|
if field.respond_to?(:foreign_key) &&
|
146
|
-
|
147
|
-
|
146
|
+
reflection.inverse_of.present? &&
|
147
|
+
reflection.inverse_of.foreign_key == field.foreign_key
|
148
148
|
is_valid = false
|
149
149
|
end
|
150
150
|
|
151
151
|
# polymorphic association
|
152
152
|
if field.respond_to?(:foreign_key) &&
|
153
|
-
|
154
|
-
|
155
|
-
|
153
|
+
field.is_polymorphic? &&
|
154
|
+
reflection.respond_to?(:polymorphic?) &&
|
155
|
+
reflection.inverse_of.foreign_key == field.reflection.foreign_key
|
156
156
|
is_valid = false
|
157
157
|
end
|
158
158
|
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
|
data/lib/avo/version.rb
CHANGED
data/public/avo-assets/avo.js
CHANGED
@@ -17916,7 +17916,7 @@
|
|
17916
17916
|
function isInteger(value) {
|
17917
17917
|
return /^[0-9]+$/.test(value);
|
17918
17918
|
}
|
17919
|
-
URI3.version = "1.19.
|
17919
|
+
URI3.version = "1.19.10";
|
17920
17920
|
var p2 = URI3.prototype;
|
17921
17921
|
var hasOwn = Object.prototype.hasOwnProperty;
|
17922
17922
|
function escapeRegEx(string) {
|
@@ -18026,6 +18026,7 @@
|
|
18026
18026
|
trim: /[`!()\[\]{};:'".,<>?«»“”„‘’]+$/,
|
18027
18027
|
parens: /(\([^\)]*\)|\[[^\]]*\]|\{[^}]*\}|<[^>]*>)/g
|
18028
18028
|
};
|
18029
|
+
URI3.leading_whitespace_expression = /^[\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/;
|
18029
18030
|
URI3.defaultPorts = {
|
18030
18031
|
http: "80",
|
18031
18032
|
https: "443",
|
@@ -18223,6 +18224,7 @@
|
|
18223
18224
|
preventInvalidHostname: URI3.preventInvalidHostname
|
18224
18225
|
};
|
18225
18226
|
}
|
18227
|
+
string = string.replace(URI3.leading_whitespace_expression, "");
|
18226
18228
|
pos = string.indexOf("#");
|
18227
18229
|
if (pos > -1) {
|
18228
18230
|
parts.fragment = string.substring(pos + 1) || null;
|
@@ -18233,7 +18235,7 @@
|
|
18233
18235
|
parts.query = string.substring(pos + 1) || null;
|
18234
18236
|
string = string.substring(0, pos);
|
18235
18237
|
}
|
18236
|
-
string = string.replace(/^(https?|ftp|wss?)
|
18238
|
+
string = string.replace(/^(https?|ftp|wss?)?:+[/\\]*/i, "$1://");
|
18237
18239
|
if (string.substring(0, 2) === "//") {
|
18238
18240
|
parts.protocol = null;
|
18239
18241
|
string = string.substring(2);
|
@@ -88687,7 +88689,7 @@
|
|
88687
88689
|
/*!
|
88688
88690
|
* URI.js - Mutating URLs
|
88689
88691
|
*
|
88690
|
-
* Version: 1.19.
|
88692
|
+
* Version: 1.19.10
|
88691
88693
|
*
|
88692
88694
|
* Author: Rodney Rehm
|
88693
88695
|
* Web: http://medialize.github.io/URI.js/
|
@@ -88700,7 +88702,7 @@
|
|
88700
88702
|
* URI.js - Mutating URLs
|
88701
88703
|
* IPv6 Support
|
88702
88704
|
*
|
88703
|
-
* Version: 1.19.
|
88705
|
+
* Version: 1.19.10
|
88704
88706
|
*
|
88705
88707
|
* Author: Rodney Rehm
|
88706
88708
|
* Web: http://medialize.github.io/URI.js/
|
@@ -88713,7 +88715,7 @@
|
|
88713
88715
|
* URI.js - Mutating URLs
|
88714
88716
|
* Second Level Domain (SLD) Support
|
88715
88717
|
*
|
88716
|
-
* Version: 1.19.
|
88718
|
+
* Version: 1.19.10
|
88717
88719
|
*
|
88718
88720
|
* Author: Rodney Rehm
|
88719
88721
|
* Web: http://medialize.github.io/URI.js/
|