avo 1.21.0.pre.1 → 1.22.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 +3 -1
- data/Gemfile.lock +61 -61
- data/README.md +1 -1
- data/app/assets/svgs/x.svg +3 -0
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +29 -0
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +77 -0
- data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +73 -46
- data/app/components/avo/fields/belongs_to_field/edit_component.rb +37 -0
- data/app/components/avo/navigation_link_component.html.erb +1 -1
- data/app/components/avo/navigation_link_component.rb +2 -1
- data/app/components/avo/views/resource_index_component.html.erb +1 -1
- data/app/controllers/avo/application_controller.rb +16 -14
- data/app/controllers/avo/base_controller.rb +1 -4
- data/app/controllers/avo/relations_controller.rb +4 -4
- data/app/controllers/avo/search_controller.rb +0 -1
- data/app/javascript/js/controllers/fields/belongs_to_field_controller.js +96 -33
- data/app/javascript/js/controllers/fields/date_field_controller.js +10 -2
- data/app/javascript/js/controllers/item_selector_controller.js +29 -19
- data/app/javascript/js/controllers/search_controller.js +88 -17
- data/app/views/avo/partials/_global_search.html.erb +0 -1
- data/app/views/avo/partials/_javascript.html.erb +1 -0
- data/app/views/avo/partials/_logo.html.erb +3 -1
- data/app/views/avo/partials/_resource_search.html.erb +0 -1
- data/app/views/avo/partials/_turbo_frame_wrap.html.erb +7 -1
- data/app/views/avo/sidebar/_sidebar.html.erb +1 -3
- data/db/factories.rb +11 -3
- data/lib/avo/base_resource.rb +16 -14
- data/lib/avo/fields/base_field.rb +1 -1
- data/lib/avo/fields/belongs_to_field.rb +19 -2
- data/lib/avo/fields/files_field.rb +2 -1
- data/lib/avo/fields/key_value_field.rb +28 -8
- data/lib/avo/licensing/pro_license.rb +2 -1
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/locales/avo.en.yml +2 -0
- data/lib/generators/avo/templates/locales/avo.nb-NO.yml +1 -0
- data/lib/generators/avo/templates/locales/avo.pt-BR.yml +1 -0
- data/lib/generators/avo/templates/locales/avo.ro.yml +1 -0
- data/public/avo-assets/avo.css +20 -4
- data/public/avo-assets/avo.js +330 -237
- data/public/avo-assets/avo.js.map +2 -2
- metadata +7 -7
- data/app/assets/builds/avo.css +0 -8590
- data/app/assets/builds/avo.js +0 -87755
- data/app/assets/builds/avo.js.map +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 629be34248470405b26afdad89b08373587cd4ea00fb10f910315072338b5f39
|
4
|
+
data.tar.gz: ef5eb75f5e6b863af0d69fdefee87455a44283a17333000adcb2ab076f827fb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35cc7ab3e7086fd1b701e8600f25a33f3a7b779d03626ea293b75e19f375e4de5bc4ab29dc243d49eeb9bd0afe5411d35c87165aac01ca029b2de9cee6f6e1f1
|
7
|
+
data.tar.gz: 0b4e462976362acfaf3ecf5673a70f474f1c0c4b0e11d7f502c81cf3a9f53def31306988defa28599de643c10f9a4ee27b77182e1f6231d509cd1374e9cebd84
|
data/Gemfile
CHANGED
@@ -30,7 +30,7 @@ gem "rails", "~> 6.1.0"
|
|
30
30
|
# Use postgresql as the database for Active Record
|
31
31
|
gem "pg", ">= 0.18", "< 2.0"
|
32
32
|
# Use Puma as the app server
|
33
|
-
gem "puma", "~> 5.
|
33
|
+
gem "puma", "~> 5.6.2"
|
34
34
|
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
|
35
35
|
# gem "jbuilder", "~> 2.7"
|
36
36
|
# Use Redis adapter to run Action Cable in production
|
@@ -77,6 +77,8 @@ group :development do
|
|
77
77
|
# gem 'ruby-prof'
|
78
78
|
|
79
79
|
# gem 'pry-rails'
|
80
|
+
|
81
|
+
gem 'htmlbeautifier'
|
80
82
|
end
|
81
83
|
|
82
84
|
group :development, :test do
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (1.
|
4
|
+
avo (1.22.0)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
@@ -19,40 +19,40 @@ PATH
|
|
19
19
|
GEM
|
20
20
|
remote: https://rubygems.org/
|
21
21
|
specs:
|
22
|
-
actioncable (6.1.4.
|
23
|
-
actionpack (= 6.1.4.
|
24
|
-
activesupport (= 6.1.4.
|
22
|
+
actioncable (6.1.4.6)
|
23
|
+
actionpack (= 6.1.4.6)
|
24
|
+
activesupport (= 6.1.4.6)
|
25
25
|
nio4r (~> 2.0)
|
26
26
|
websocket-driver (>= 0.6.1)
|
27
|
-
actionmailbox (6.1.4.
|
28
|
-
actionpack (= 6.1.4.
|
29
|
-
activejob (= 6.1.4.
|
30
|
-
activerecord (= 6.1.4.
|
31
|
-
activestorage (= 6.1.4.
|
32
|
-
activesupport (= 6.1.4.
|
27
|
+
actionmailbox (6.1.4.6)
|
28
|
+
actionpack (= 6.1.4.6)
|
29
|
+
activejob (= 6.1.4.6)
|
30
|
+
activerecord (= 6.1.4.6)
|
31
|
+
activestorage (= 6.1.4.6)
|
32
|
+
activesupport (= 6.1.4.6)
|
33
33
|
mail (>= 2.7.1)
|
34
|
-
actionmailer (6.1.4.
|
35
|
-
actionpack (= 6.1.4.
|
36
|
-
actionview (= 6.1.4.
|
37
|
-
activejob (= 6.1.4.
|
38
|
-
activesupport (= 6.1.4.
|
34
|
+
actionmailer (6.1.4.6)
|
35
|
+
actionpack (= 6.1.4.6)
|
36
|
+
actionview (= 6.1.4.6)
|
37
|
+
activejob (= 6.1.4.6)
|
38
|
+
activesupport (= 6.1.4.6)
|
39
39
|
mail (~> 2.5, >= 2.5.4)
|
40
40
|
rails-dom-testing (~> 2.0)
|
41
|
-
actionpack (6.1.4.
|
42
|
-
actionview (= 6.1.4.
|
43
|
-
activesupport (= 6.1.4.
|
41
|
+
actionpack (6.1.4.6)
|
42
|
+
actionview (= 6.1.4.6)
|
43
|
+
activesupport (= 6.1.4.6)
|
44
44
|
rack (~> 2.0, >= 2.0.9)
|
45
45
|
rack-test (>= 0.6.3)
|
46
46
|
rails-dom-testing (~> 2.0)
|
47
47
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
48
|
-
actiontext (6.1.4.
|
49
|
-
actionpack (= 6.1.4.
|
50
|
-
activerecord (= 6.1.4.
|
51
|
-
activestorage (= 6.1.4.
|
52
|
-
activesupport (= 6.1.4.
|
48
|
+
actiontext (6.1.4.6)
|
49
|
+
actionpack (= 6.1.4.6)
|
50
|
+
activerecord (= 6.1.4.6)
|
51
|
+
activestorage (= 6.1.4.6)
|
52
|
+
activesupport (= 6.1.4.6)
|
53
53
|
nokogiri (>= 1.8.5)
|
54
|
-
actionview (6.1.4.
|
55
|
-
activesupport (= 6.1.4.
|
54
|
+
actionview (6.1.4.6)
|
55
|
+
activesupport (= 6.1.4.6)
|
56
56
|
builder (~> 3.1)
|
57
57
|
erubi (~> 1.4)
|
58
58
|
rails-dom-testing (~> 2.0)
|
@@ -60,22 +60,22 @@ GEM
|
|
60
60
|
active_link_to (1.0.5)
|
61
61
|
actionpack
|
62
62
|
addressable
|
63
|
-
activejob (6.1.4.
|
64
|
-
activesupport (= 6.1.4.
|
63
|
+
activejob (6.1.4.6)
|
64
|
+
activesupport (= 6.1.4.6)
|
65
65
|
globalid (>= 0.3.6)
|
66
|
-
activemodel (6.1.4.
|
67
|
-
activesupport (= 6.1.4.
|
68
|
-
activerecord (6.1.4.
|
69
|
-
activemodel (= 6.1.4.
|
70
|
-
activesupport (= 6.1.4.
|
71
|
-
activestorage (6.1.4.
|
72
|
-
actionpack (= 6.1.4.
|
73
|
-
activejob (= 6.1.4.
|
74
|
-
activerecord (= 6.1.4.
|
75
|
-
activesupport (= 6.1.4.
|
66
|
+
activemodel (6.1.4.6)
|
67
|
+
activesupport (= 6.1.4.6)
|
68
|
+
activerecord (6.1.4.6)
|
69
|
+
activemodel (= 6.1.4.6)
|
70
|
+
activesupport (= 6.1.4.6)
|
71
|
+
activestorage (6.1.4.6)
|
72
|
+
actionpack (= 6.1.4.6)
|
73
|
+
activejob (= 6.1.4.6)
|
74
|
+
activerecord (= 6.1.4.6)
|
75
|
+
activesupport (= 6.1.4.6)
|
76
76
|
marcel (~> 1.0.0)
|
77
77
|
mini_mime (>= 1.1.0)
|
78
|
-
activesupport (6.1.4.
|
78
|
+
activesupport (6.1.4.6)
|
79
79
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
80
80
|
i18n (>= 1.6, < 2)
|
81
81
|
minitest (>= 5.1)
|
@@ -175,10 +175,11 @@ GEM
|
|
175
175
|
rails (>= 6.0.0)
|
176
176
|
stimulus-rails
|
177
177
|
turbo-rails
|
178
|
+
htmlbeautifier (1.4.1)
|
178
179
|
httparty (0.20.0)
|
179
180
|
mime-types (~> 3.0)
|
180
181
|
multi_xml (>= 0.5.2)
|
181
|
-
i18n (1.
|
182
|
+
i18n (1.10.0)
|
182
183
|
concurrent-ruby (~> 1.0)
|
183
184
|
i18n_data (0.15.0)
|
184
185
|
simple_po_parser (~> 1.1)
|
@@ -196,7 +197,7 @@ GEM
|
|
196
197
|
listen (3.7.1)
|
197
198
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
198
199
|
rb-inotify (~> 0.9, >= 0.9.10)
|
199
|
-
loofah (2.
|
200
|
+
loofah (2.14.0)
|
200
201
|
crass (~> 1.0.2)
|
201
202
|
nokogiri (>= 1.5.9)
|
202
203
|
mail (2.7.1)
|
@@ -229,8 +230,6 @@ GEM
|
|
229
230
|
nokogiri (1.13.1)
|
230
231
|
mini_portile2 (~> 2.7.0)
|
231
232
|
racc (~> 1.4)
|
232
|
-
nokogiri (1.13.1-x86_64-linux)
|
233
|
-
racc (~> 1.4)
|
234
233
|
orm_adapter (0.5.0)
|
235
234
|
pagy (5.10.1)
|
236
235
|
activesupport
|
@@ -239,28 +238,28 @@ GEM
|
|
239
238
|
ast (~> 2.4.1)
|
240
239
|
pg (1.3.1)
|
241
240
|
public_suffix (4.0.6)
|
242
|
-
puma (5.
|
241
|
+
puma (5.6.2)
|
243
242
|
nio4r (~> 2.0)
|
244
|
-
pundit (2.
|
243
|
+
pundit (2.2.0)
|
245
244
|
activesupport (>= 3.0.0)
|
246
245
|
racc (1.6.0)
|
247
246
|
rack (2.2.3)
|
248
247
|
rack-test (1.1.0)
|
249
248
|
rack (>= 1.0, < 3)
|
250
|
-
rails (6.1.4.
|
251
|
-
actioncable (= 6.1.4.
|
252
|
-
actionmailbox (= 6.1.4.
|
253
|
-
actionmailer (= 6.1.4.
|
254
|
-
actionpack (= 6.1.4.
|
255
|
-
actiontext (= 6.1.4.
|
256
|
-
actionview (= 6.1.4.
|
257
|
-
activejob (= 6.1.4.
|
258
|
-
activemodel (= 6.1.4.
|
259
|
-
activerecord (= 6.1.4.
|
260
|
-
activestorage (= 6.1.4.
|
261
|
-
activesupport (= 6.1.4.
|
249
|
+
rails (6.1.4.6)
|
250
|
+
actioncable (= 6.1.4.6)
|
251
|
+
actionmailbox (= 6.1.4.6)
|
252
|
+
actionmailer (= 6.1.4.6)
|
253
|
+
actionpack (= 6.1.4.6)
|
254
|
+
actiontext (= 6.1.4.6)
|
255
|
+
actionview (= 6.1.4.6)
|
256
|
+
activejob (= 6.1.4.6)
|
257
|
+
activemodel (= 6.1.4.6)
|
258
|
+
activerecord (= 6.1.4.6)
|
259
|
+
activestorage (= 6.1.4.6)
|
260
|
+
activesupport (= 6.1.4.6)
|
262
261
|
bundler (>= 1.15.0)
|
263
|
-
railties (= 6.1.4.
|
262
|
+
railties (= 6.1.4.6)
|
264
263
|
sprockets-rails (>= 2.0.0)
|
265
264
|
rails-controller-testing (1.0.5)
|
266
265
|
actionpack (>= 5.0.1.rc1)
|
@@ -271,9 +270,9 @@ GEM
|
|
271
270
|
nokogiri (>= 1.6)
|
272
271
|
rails-html-sanitizer (1.4.2)
|
273
272
|
loofah (~> 2.3)
|
274
|
-
railties (6.1.4.
|
275
|
-
actionpack (= 6.1.4.
|
276
|
-
activesupport (= 6.1.4.
|
273
|
+
railties (6.1.4.6)
|
274
|
+
actionpack (= 6.1.4.6)
|
275
|
+
activesupport (= 6.1.4.6)
|
277
276
|
method_source
|
278
277
|
rake (>= 0.13)
|
279
278
|
thor (~> 1.0)
|
@@ -419,6 +418,7 @@ DEPENDENCIES
|
|
419
418
|
fuubar
|
420
419
|
gem-release
|
421
420
|
hotwire-rails
|
421
|
+
htmlbeautifier
|
422
422
|
httparty
|
423
423
|
image_processing (~> 1.2)
|
424
424
|
iso
|
@@ -429,7 +429,7 @@ DEPENDENCIES
|
|
429
429
|
meta-tags
|
430
430
|
net-smtp
|
431
431
|
pg (>= 0.18, < 2.0)
|
432
|
-
puma (~> 5.
|
432
|
+
puma (~> 5.6.2)
|
433
433
|
pundit
|
434
434
|
rails (~> 6.1.0)
|
435
435
|
rails-controller-testing
|
data/README.md
CHANGED
@@ -54,7 +54,7 @@ $ bundle install
|
|
54
54
|
|
55
55
|
# Quick Purchase
|
56
56
|
|
57
|
-
Use [this](https://
|
57
|
+
Use [this](https://avohq.io/purchase/pro) link to quickly purchase a Pro license to support this project. Thank you 🙏
|
58
58
|
|
59
59
|
# Contributing
|
60
60
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<div data-controller="search" class="resource-search flex items-center h-full w-full" data-turbo-remove-before-cache>
|
2
|
+
<div class="w-full hidden"
|
3
|
+
data-search-target="autocomplete"
|
4
|
+
data-search-resource="<%= @model_key %>"
|
5
|
+
data-translation-keys='{"no_item_found": "<%= I18n.translate 'avo.no_item_found' %>"}'
|
6
|
+
data-via-association="belongs_to"
|
7
|
+
></div>
|
8
|
+
<div class="relative w-full" autocomplete="off">
|
9
|
+
<%= @form.text_field @field.foreign_key,
|
10
|
+
value: field_label,
|
11
|
+
class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
|
12
|
+
placeholder: @field.placeholder,
|
13
|
+
'data-search-target': 'button clearValue',
|
14
|
+
# This instructs the search_controller if it should enable/disabled this field when the user switches polymorphic associations
|
15
|
+
# It should not enable the field if the record is being created through an association
|
16
|
+
'data-should-be-disabled': @disabled,
|
17
|
+
disabled: true %>
|
18
|
+
<% unless @disabled %>
|
19
|
+
<div class="absolute top-1/2 left-auto right-3 mr-px -mt-2 cursor-pointer hidden text-gray-500"
|
20
|
+
data-tippy="tooltip"
|
21
|
+
data-search-target="clearButton"
|
22
|
+
title="<%= I18n.translate 'avo.clear_value' %>"
|
23
|
+
data-action="click->search#clearValue"
|
24
|
+
><%= helpers.svg 'x', class: 'h-4' %>
|
25
|
+
</div>
|
26
|
+
<% end %>
|
27
|
+
</div>
|
28
|
+
<%= @form.hidden_field @foreign_key, value: field_value, 'data-search-target': 'hiddenId clearValue' %>
|
29
|
+
</div>
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
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)
|
5
|
+
@form = form
|
6
|
+
@field = field
|
7
|
+
@type = type
|
8
|
+
@model_key = model_key
|
9
|
+
@foreign_key = foreign_key
|
10
|
+
@resource = resource
|
11
|
+
@disabled = disabled
|
12
|
+
@polymorphic_record = polymorphic_record
|
13
|
+
end
|
14
|
+
|
15
|
+
def field_label
|
16
|
+
if searchable?
|
17
|
+
# New records won't have the value (instantiated model) present but the polymorphic_type and polymorphic_id prefilled
|
18
|
+
if new_record? && has_polymorphic_association?
|
19
|
+
@polymorphic_record.send(polymorphic_fields[:label])
|
20
|
+
else
|
21
|
+
@field.value&.class == @type ? @field.field_label : nil
|
22
|
+
end
|
23
|
+
else
|
24
|
+
@field.field_label
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def field_value
|
29
|
+
if searchable?
|
30
|
+
# New records won't have the value (instantiated model) present but the polymorphic_type and polymorphic_id prefilled
|
31
|
+
if new_record? && has_polymorphic_association?
|
32
|
+
@polymorphic_record.send(polymorphic_fields[:id])
|
33
|
+
else
|
34
|
+
@field.value&.class == @type ? @field.field_value : nil
|
35
|
+
end
|
36
|
+
else
|
37
|
+
@field.field_value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def searchable?
|
44
|
+
@type.present?
|
45
|
+
end
|
46
|
+
|
47
|
+
def new_record?
|
48
|
+
@resource.model.new_record?
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_polymorphic_association?
|
52
|
+
polymorphic_class.present? && polymorphic_id.present?
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get the polymorphic class
|
56
|
+
def polymorphic_class
|
57
|
+
@resource.model["#{@field.foreign_key}_type"]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Get the polymorphic id
|
61
|
+
def polymorphic_id
|
62
|
+
@resource.model["#{@field.foreign_key}_id"]
|
63
|
+
end
|
64
|
+
|
65
|
+
# Get the resource for that polymorphic class
|
66
|
+
def polymorphic_resource
|
67
|
+
::Avo::App.get_resource_by_model_name polymorphic_class
|
68
|
+
end
|
69
|
+
|
70
|
+
# Extract the needed fields to identify the record for polymorphic associations
|
71
|
+
def polymorphic_fields
|
72
|
+
{
|
73
|
+
id: polymorphic_resource.id,
|
74
|
+
label: polymorphic_resource.title
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
@@ -1,68 +1,95 @@
|
|
1
|
-
<%
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
1
|
+
<%
|
2
|
+
if is_polymorphic?
|
3
|
+
|
4
|
+
# Set the model keys so we can pass them over
|
5
|
+
model_keys = @field.types.map do |type|
|
6
|
+
resource = Avo::App.get_resource_by_model_name(type.to_s)
|
7
|
+
[type.to_s, resource.model_key]
|
8
|
+
end.to_h
|
9
|
+
%>
|
10
|
+
<div data-controller="belongs-to-field"
|
11
|
+
data-searchable="<%= @field.searchable %>"
|
12
|
+
data-association="<%= @field.id %>"
|
13
|
+
data-association-class="<%= @field&.target_resource&.model_class || nil %>"
|
14
|
+
>
|
15
|
+
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal do %>
|
16
|
+
<%= @form.select "#{@field.foreign_key}_type", @field.types.map { |type| [type.to_s.underscore.humanize, type.to_s] },
|
17
|
+
{
|
18
|
+
value: @field.value,
|
19
|
+
include_blank: @field.placeholder,
|
20
|
+
},
|
21
|
+
{
|
22
|
+
class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
|
23
|
+
disabled: disabled,
|
24
|
+
'data-belongs-to-field-target': "select",
|
25
|
+
'data-action': 'change->belongs-to-field#changeType'
|
26
|
+
}
|
27
|
+
%>
|
28
|
+
<%
|
16
29
|
# If the select field is disabled, no value will be sent. It's how HTML works.
|
17
30
|
# Thus the extra hidden field to actually send the related id to the server.
|
18
|
-
if disabled
|
19
|
-
%>
|
20
|
-
<%= @form.hidden_field "#{@field.foreign_key}_type" %>
|
21
|
-
<% end %>
|
31
|
+
if disabled %>
|
32
|
+
<%= @form.hidden_field "#{@field.foreign_key}_type" %>
|
22
33
|
<% end %>
|
23
|
-
|
24
|
-
|
34
|
+
<% end %>
|
35
|
+
<% @field.types.each do |type| %>
|
36
|
+
<div class="hidden"
|
25
37
|
data-belongs-to-field-target="type"
|
26
38
|
data-type="<%= type %>"
|
27
39
|
>
|
28
|
-
|
29
|
-
|
40
|
+
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal, label: type.to_s.underscore.humanize do %>
|
41
|
+
<% if @field.searchable %>
|
42
|
+
<%= render Avo::Fields::BelongsToField::AutocompleteComponent.new form: @form,
|
43
|
+
field: @field,
|
44
|
+
type: type,
|
45
|
+
model_key: model_keys[type.to_s],
|
46
|
+
foreign_key: "#{@field.foreign_key}_id",
|
47
|
+
resource: @resource,
|
48
|
+
disabled: disabled,
|
49
|
+
polymorphic_record: polymorphic_record
|
50
|
+
%>
|
51
|
+
<% else %>
|
52
|
+
<%= @form.select "#{@field.foreign_key}_id", options_for_select(@field.values_for_type(type), @resource.present? && @resource.model.present? ? @resource.model["#{@field.foreign_key}_id"] : nil),
|
30
53
|
{
|
54
|
+
value: @resource.model["#{@field.foreign_key}_id"].to_s,
|
31
55
|
include_blank: @field.placeholder,
|
32
56
|
},
|
33
57
|
{
|
34
58
|
class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
|
35
59
|
disabled: disabled
|
36
60
|
}
|
37
|
-
%>
|
38
|
-
<%
|
39
|
-
# If the select field is disabled, no value will be sent. It's how HTML works.
|
40
|
-
# Thus the extra hidden field to actually send the related id to the server.
|
41
|
-
if disabled
|
42
61
|
%>
|
43
|
-
<%= @form.hidden_field "#{@field.foreign_key}_id" %>
|
44
|
-
<% end %>
|
45
62
|
<% end %>
|
46
|
-
|
47
|
-
|
48
|
-
|
63
|
+
<% end %>
|
64
|
+
</div>
|
65
|
+
<% end %>
|
66
|
+
</div>
|
49
67
|
<% else %>
|
50
68
|
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal do %>
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
69
|
+
<% if @field.searchable %>
|
70
|
+
<%= render Avo::Fields::BelongsToField::AutocompleteComponent.new form: @form,
|
71
|
+
field: @field,
|
72
|
+
model_key: @field.target_resource&.model_key,
|
73
|
+
foreign_key: @field.foreign_key,
|
74
|
+
resource: @resource,
|
57
75
|
disabled: disabled
|
58
|
-
}
|
59
76
|
%>
|
60
|
-
<%
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
77
|
+
<% else %>
|
78
|
+
<%= @form.select @field.foreign_key, @field.options.map { |o| [o[:label], o[:value]] },
|
79
|
+
{
|
80
|
+
include_blank: @field.placeholder,
|
81
|
+
},
|
82
|
+
{
|
83
|
+
class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
|
84
|
+
disabled: disabled
|
85
|
+
}
|
86
|
+
%>
|
87
|
+
<%
|
88
|
+
# If the select field is disabled, no value will be sent. It's how HTML works.
|
89
|
+
# Thus the extra hidden field to actually send the related id to the server.
|
90
|
+
if disabled %>
|
91
|
+
<%= @form.hidden_field @field.foreign_key %>
|
92
|
+
<% end %>
|
66
93
|
<% end %>
|
67
94
|
<% end %>
|
68
95
|
<% end %>
|
@@ -1,6 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
|
4
|
+
def initialize(field: nil, resource: nil, index: 0, form: nil, displayed_in_modal: false)
|
5
|
+
super field: field, resource: resource, index: index, form: form, displayed_in_modal: displayed_in_modal
|
6
|
+
|
7
|
+
@polymorphic_record = nil
|
8
|
+
end
|
9
|
+
|
4
10
|
def disabled
|
5
11
|
return true if @field.readonly
|
6
12
|
return true if @field.target_resource.present? && @field.target_resource.model_class.name == params[:via_resource_class]
|
@@ -8,4 +14,35 @@ class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
|
|
8
14
|
|
9
15
|
false
|
10
16
|
end
|
17
|
+
|
18
|
+
def is_polymorphic?
|
19
|
+
@field.types.present?
|
20
|
+
end
|
21
|
+
|
22
|
+
def has_polymorphic_association?
|
23
|
+
polymorphic_class.present? && polymorphic_id.present?
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get the polymorphic class
|
27
|
+
def polymorphic_class
|
28
|
+
@resource.model["#{@field.foreign_key}_type"]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get the polymorphic id
|
32
|
+
def polymorphic_id
|
33
|
+
@resource.model["#{@field.foreign_key}_id"]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Get the actual resource
|
37
|
+
def polymorphic_record
|
38
|
+
return unless has_polymorphic_association?
|
39
|
+
|
40
|
+
return unless is_polymorphic?
|
41
|
+
|
42
|
+
return @polymorphic_record if @polymorphic_record.present?
|
43
|
+
|
44
|
+
@polymorphic_record = polymorphic_class.safe_constantize.find polymorphic_id
|
45
|
+
|
46
|
+
@polymorphic_record
|
47
|
+
end
|
11
48
|
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
<%= active_link_to @path, class: 'text-gray-800 py-2 px-4 block font-normal hover:bg-gray-100 rounded-md mb-1 mx-3 text-sm leading-none', active: @active do %>
|
1
|
+
<%= active_link_to @path, class: 'text-gray-800 py-2 px-4 block font-normal hover:bg-gray-100 rounded-md mb-1 mx-3 text-sm leading-none', active: @active, target: @target do %>
|
2
2
|
<div class="w-4"></div> <%= @label %>
|
3
3
|
<% end %>
|
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::NavigationLinkComponent < ViewComponent::Base
|
4
|
-
def initialize(label: nil, path: nil, active: :inclusive, size: :md)
|
4
|
+
def initialize(label: nil, path: nil, active: :inclusive, size: :md, target: "_self")
|
5
5
|
@label = label
|
6
6
|
@path = path
|
7
7
|
@active = active
|
8
8
|
@size = size
|
9
|
+
@target = target
|
9
10
|
end
|
10
11
|
end
|
@@ -24,7 +24,7 @@
|
|
24
24
|
data-selected-resources="[]"
|
25
25
|
>
|
26
26
|
<div class="flex items-center px-6 w-64">
|
27
|
-
<%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.
|
27
|
+
<%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.model_key} if @resource.search_query.present? %>
|
28
28
|
</div>
|
29
29
|
<div class="flex justify-end items-center px-6 space-x-3">
|
30
30
|
<%= render partial: 'avo/partials/view_toggle_button', locals: { available_view_types: available_view_types, view_type: view_type, turbo_frame: @turbo_frame } if @models.present? %>
|
@@ -1,6 +1,11 @@
|
|
1
1
|
module Avo
|
2
2
|
class ApplicationController < ::ActionController::Base
|
3
|
-
|
3
|
+
if defined?(Pundit::Authorization)
|
4
|
+
include Pundit::Authorization
|
5
|
+
else
|
6
|
+
include Pundit
|
7
|
+
end
|
8
|
+
|
4
9
|
include Pagy::Backend
|
5
10
|
include Avo::ApplicationHelper
|
6
11
|
include Avo::UrlHelpers
|
@@ -111,7 +116,12 @@ module Avo
|
|
111
116
|
end
|
112
117
|
|
113
118
|
def fill_model
|
114
|
-
|
119
|
+
# We have to skip filling the the model if this is an attach action
|
120
|
+
is_attach_action = params[model_param_key].blank? && params[:related_name].present? && params[:fields].present?
|
121
|
+
|
122
|
+
unless is_attach_action
|
123
|
+
@model = @resource.fill_model(@model_to_fill, cast_nullable(model_params))
|
124
|
+
end
|
115
125
|
end
|
116
126
|
|
117
127
|
def hydrate_resource
|
@@ -187,18 +197,6 @@ module Avo
|
|
187
197
|
query
|
188
198
|
end
|
189
199
|
|
190
|
-
# def authorize_user
|
191
|
-
# return if params[:controller] == 'avo/search'
|
192
|
-
|
193
|
-
# model = record = resource.model
|
194
|
-
|
195
|
-
# if ['show', 'edit', 'update'].include?(params[:action]) && params[:controller] == 'avo/resources'
|
196
|
-
# record = resource
|
197
|
-
# end
|
198
|
-
|
199
|
-
# # AuthorizationService::authorize_action _current_user, record, params[:action] return render_unauthorized unless
|
200
|
-
# end
|
201
|
-
|
202
200
|
def _authenticate!
|
203
201
|
instance_eval(&Avo.configuration.authenticate)
|
204
202
|
end
|
@@ -243,5 +241,9 @@ module Avo
|
|
243
241
|
def on_api_path
|
244
242
|
request.original_url.match?(/.*#{Avo::App.root_path}\/avo_api\/.*/)
|
245
243
|
end
|
244
|
+
|
245
|
+
def model_param_key
|
246
|
+
@resource.form_scope
|
247
|
+
end
|
246
248
|
end
|
247
249
|
end
|