avo 1.6.2.pre.1 → 1.7.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 +6 -6
- data/README.md +2 -2
- data/app/components/avo/edit/field_wrapper_component.html.erb +1 -1
- data/app/components/avo/edit/field_wrapper_component.rb +6 -1
- data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +65 -15
- data/app/components/avo/fields/belongs_to_field/edit_component.rb +1 -1
- data/app/controllers/avo/base_controller.rb +6 -1
- data/app/packs/js/controllers/fields/belongs_to_field_controller.js +65 -0
- data/db/factories.rb +4 -0
- data/lib/avo/base_resource.rb +36 -41
- data/lib/avo/fields/base_field.rb +5 -3
- data/lib/avo/fields/belongs_to_field.rb +96 -12
- data/lib/avo/fields/boolean_group_field.rb +1 -1
- data/lib/avo/fields/date_time_field.rb +1 -1
- data/lib/avo/fields/files_field.rb +1 -1
- data/lib/avo/fields/has_one_field.rb +1 -1
- data/lib/avo/fields/key_value_field.rb +1 -1
- data/lib/avo/fields/select_field.rb +17 -4
- data/lib/avo/fields_collector.rb +0 -2
- data/lib/avo/version.rb +1 -1
- data/public/avo-packs/css/application-797341b7.css.map +1 -1
- data/public/avo-packs/css/application-797341b7.css.map.br +0 -0
- data/public/avo-packs/css/application-797341b7.css.map.gz +0 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js +26 -0
- data/public/avo-packs/js/{application-b444cbf11135b4b23654.js.LICENSE.txt → application-947ed727440d5b5d73ab.js.LICENSE.txt} +0 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js.br +0 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js.gz +0 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js.map +1 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js.map.br +0 -0
- data/public/avo-packs/js/application-947ed727440d5b5d73ab.js.map.gz +0 -0
- data/public/avo-packs/manifest.json +8 -8
- metadata +12 -11
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js +0 -26
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js.br +0 -0
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js.gz +0 -0
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js.map +0 -1
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js.map.br +0 -0
- data/public/avo-packs/js/application-b444cbf11135b4b23654.js.map.gz +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e58bf8c94a89819523d1ef5abf6390ea2fb754d589c434a5de0d9daef0a231d0
|
4
|
+
data.tar.gz: 4662ea67f1f2653a495617d02ea279ed919889d33c599642394ca3f35e726f1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6743f19e795f59bed7ac32436e67a73a8bfbfdb7d267dd12de510d93d64bfe7f592cf400c1aef2e1cab4538ada6b614191aac596ecd3f19444b9ef0fb42e8518
|
7
|
+
data.tar.gz: 16360a9602b08cc7f973cddda9106546c6cded669ce9592d80b6b647a0e53ec1f3d74468f8d04c8db632610059e234552b3b5debfa444489af0b4090677e4e96
|
data/Gemfile
CHANGED
@@ -30,7 +30,7 @@ gem "rails", "~> 6.0.2", ">= 6.0.2.2"
|
|
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", "~>
|
33
|
+
gem "puma", "~> 5.3.1"
|
34
34
|
# Use SCSS for stylesheets
|
35
35
|
gem "sass-rails", ">= 6"
|
36
36
|
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (1.
|
4
|
+
avo (1.7.0)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
@@ -184,10 +184,10 @@ GEM
|
|
184
184
|
msgpack (1.4.2)
|
185
185
|
multi_xml (0.6.0)
|
186
186
|
nio4r (2.5.7)
|
187
|
-
nokogiri (1.11.
|
187
|
+
nokogiri (1.11.5)
|
188
188
|
mini_portile2 (~> 2.5.0)
|
189
189
|
racc (~> 1.4)
|
190
|
-
nokogiri (1.11.
|
190
|
+
nokogiri (1.11.5-x86_64-linux)
|
191
191
|
racc (~> 1.4)
|
192
192
|
orm_adapter (0.5.0)
|
193
193
|
pagy (3.13.0)
|
@@ -196,7 +196,7 @@ GEM
|
|
196
196
|
ast (~> 2.4.1)
|
197
197
|
pg (1.2.3)
|
198
198
|
public_suffix (4.0.6)
|
199
|
-
puma (
|
199
|
+
puma (5.3.1)
|
200
200
|
nio4r (~> 2.0)
|
201
201
|
pundit (2.1.0)
|
202
202
|
activesupport (>= 3.0.0)
|
@@ -333,7 +333,7 @@ GEM
|
|
333
333
|
thread_safe (~> 0.1)
|
334
334
|
unicode-display_width (2.0.0)
|
335
335
|
unicode_utils (1.4.0)
|
336
|
-
view_component (2.
|
336
|
+
view_component (2.32.0)
|
337
337
|
activesupport (>= 5.0.0, < 7.0)
|
338
338
|
warden (1.2.9)
|
339
339
|
rack (>= 2.0.9)
|
@@ -394,7 +394,7 @@ DEPENDENCIES
|
|
394
394
|
manifester
|
395
395
|
meta-tags
|
396
396
|
pg (>= 0.18, < 2.0)
|
397
|
-
puma (~>
|
397
|
+
puma (~> 5.3.1)
|
398
398
|
pundit
|
399
399
|
rails (~> 6.0.2, >= 6.0.2.2)
|
400
400
|
rails-controller-testing
|
data/README.md
CHANGED
@@ -56,6 +56,6 @@ $ bundle install
|
|
56
56
|
|
57
57
|
Please read [CONTRIBUTING.MD](./CONTRIBUTING.MD)
|
58
58
|
|
59
|
-
# Upgrade
|
59
|
+
# Upgrade Guide
|
60
60
|
|
61
|
-
Please read the [UPGRADE_GUIDE.MD](https://docs.avohq.io/0
|
61
|
+
Please read the [UPGRADE_GUIDE.MD](https://docs.avohq.io/1.0/upgrade.html)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<div class="flex items-center py-0 leading-tight <%= @classes %> min-h-16" data-field-id="<%= @field.id %>" data-field-type="<%= @field.type %>">
|
2
2
|
<div class="h-16 flex self-start items-center text-blue-gray-800">
|
3
3
|
<div class="<% if @displayed_in_modal %> md:w-48 <% else %> md:w-64 <% end %> w-48 px-8 flex" data-slot="label">
|
4
|
-
<%= @form.label @field.id,
|
4
|
+
<%= @form.label @field.id, label %> <% if @field.required %> <span class="text-red-600">*</span> <% end %>
|
5
5
|
</div>
|
6
6
|
</div>
|
7
7
|
<div class="flex-1 flex flex-row min-h-inherit">
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::Edit::FieldWrapperComponent < ViewComponent::Base
|
4
|
-
def initialize(field: nil, dash_if_blank: true, full_width: false, displayed_in_modal: false, form: nil, resource: {}, **args)
|
4
|
+
def initialize(field: nil, dash_if_blank: true, full_width: false, displayed_in_modal: false, form: nil, resource: {}, label: nil, **args)
|
5
5
|
@field = field
|
6
6
|
@dash_if_blank = dash_if_blank
|
7
7
|
@classes = args[:class].present? ? args[:class] : ""
|
@@ -11,9 +11,14 @@ class Avo::Edit::FieldWrapperComponent < ViewComponent::Base
|
|
11
11
|
@resource = resource
|
12
12
|
@model = resource.present? ? resource.model : nil
|
13
13
|
@full_width = full_width
|
14
|
+
@label = label
|
14
15
|
|
15
16
|
if (@index != 0) || @displayed_in_modal
|
16
17
|
@classes += " border-t"
|
17
18
|
end
|
18
19
|
end
|
20
|
+
|
21
|
+
def label
|
22
|
+
@label || @field.name
|
23
|
+
end
|
19
24
|
end
|
@@ -1,18 +1,68 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
<% if @field.types.present? %>
|
2
|
+
<div data-controller="belongs-to-field">
|
3
|
+
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal do %>
|
4
|
+
<%= @form.select "#{@field.foreign_key}_type", @field.types.map { |type| [type.to_s.underscore.humanize, type.to_s] },
|
5
|
+
{
|
6
|
+
include_blank: @field.placeholder,
|
7
|
+
},
|
8
|
+
{
|
9
|
+
class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
|
10
|
+
disabled: disabled,
|
11
|
+
'data-belongs-to-field-target': "select",
|
12
|
+
'data-action': 'change->belongs-to-field#changedType'
|
13
|
+
}
|
14
|
+
%>
|
15
|
+
<%
|
16
|
+
# If the select field is disabled, no value will be sent. It's how HTML works.
|
17
|
+
# 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 %>
|
22
|
+
<% end %>
|
23
|
+
<% @field.types.each do |type| %>
|
24
|
+
<div class="hidden"
|
25
|
+
data-belongs-to-field-target="type"
|
26
|
+
data-type="<%= type %>"
|
27
|
+
>
|
28
|
+
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal, label: type.to_s.underscore.humanize do %>
|
29
|
+
<%= @form.select "#{@field.foreign_key}_id", @field.values_for_type(type),
|
30
|
+
{
|
31
|
+
include_blank: @field.placeholder,
|
32
|
+
},
|
33
|
+
{
|
34
|
+
class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
|
35
|
+
disabled: disabled
|
36
|
+
}
|
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
|
+
%>
|
43
|
+
<%= @form.hidden_field "#{@field.foreign_key}_id" %>
|
44
|
+
<% end %>
|
45
|
+
<% end %>
|
46
|
+
</div>
|
47
|
+
<% end %>
|
48
|
+
</div>
|
49
|
+
<% else %>
|
50
|
+
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal do %>
|
51
|
+
<%= @form.select @field.foreign_key, @field.options.map { |o| [o[:label], o[:value]] },
|
52
|
+
{
|
53
|
+
include_blank: @field.placeholder,
|
54
|
+
},
|
55
|
+
{
|
56
|
+
class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
|
57
|
+
disabled: disabled
|
58
|
+
}
|
59
|
+
%>
|
60
|
+
<%
|
61
|
+
# If the select field is disabled, no value will be sent. It's how HTML works.
|
62
|
+
# Thus the extra hidden field to actually send the related id to the server.
|
63
|
+
if disabled
|
10
64
|
%>
|
11
|
-
|
12
|
-
|
13
|
-
# Thus the extra hidden field to actually send the related id to the server.
|
14
|
-
if disabled
|
15
|
-
%>
|
16
|
-
<%= @form.hidden_field @field.foreign_key %>
|
65
|
+
<%= @form.hidden_field @field.foreign_key %>
|
66
|
+
<% end %>
|
17
67
|
<% end %>
|
18
68
|
<% end %>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
|
4
4
|
def disabled
|
5
5
|
return true if @field.readonly
|
6
|
-
return true if @field.target_resource.model_class.name == params[:via_resource_class]
|
6
|
+
return true if @field.target_resource.present? && @field.target_resource.model_class.name == params[:via_resource_class]
|
7
7
|
return true if @field.id.to_s == params[:via_relation].to_s
|
8
8
|
|
9
9
|
false
|
@@ -18,7 +18,12 @@ module Avo
|
|
18
18
|
|
19
19
|
# If we don't get a query object predefined from a child controller like relations, just spin one up
|
20
20
|
unless defined? @query
|
21
|
-
@query = @authorization.apply_policy @resource.model_class
|
21
|
+
@query = @authorization.apply_policy @resource.model_class
|
22
|
+
end
|
23
|
+
|
24
|
+
# Remove default_scope for index view
|
25
|
+
if @resource.unscoped_queries_on_index
|
26
|
+
@query = @query.unscoped
|
22
27
|
end
|
23
28
|
|
24
29
|
# Eager load the relations
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import { Controller } from 'stimulus'
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ['select', 'type']
|
5
|
+
|
6
|
+
get selectedType() {
|
7
|
+
return this.selectTarget.value
|
8
|
+
}
|
9
|
+
|
10
|
+
connect() {
|
11
|
+
this.setValidNames()
|
12
|
+
this.changedType()
|
13
|
+
}
|
14
|
+
|
15
|
+
setValidNames() {
|
16
|
+
this.typeTargets.forEach((target) => {
|
17
|
+
const { type } = target.dataset
|
18
|
+
const select = target.querySelector('select')
|
19
|
+
const name = select.getAttribute('name')
|
20
|
+
|
21
|
+
select.setAttribute('valid-name', name)
|
22
|
+
if (this.selectedType !== type) {
|
23
|
+
select.selectedIndex = 0
|
24
|
+
}
|
25
|
+
})
|
26
|
+
}
|
27
|
+
|
28
|
+
changedType() {
|
29
|
+
this.hideAllTypeTargets()
|
30
|
+
this.enableType(this.selectTarget.value)
|
31
|
+
}
|
32
|
+
|
33
|
+
hideAllTypeTargets() {
|
34
|
+
this.typeTargets.forEach((target) => {
|
35
|
+
this.hideTarget(target)
|
36
|
+
this.invalidateTarget(target)
|
37
|
+
})
|
38
|
+
}
|
39
|
+
|
40
|
+
hideTarget(target) {
|
41
|
+
target.classList.add('hidden')
|
42
|
+
}
|
43
|
+
|
44
|
+
invalidateTarget(target) {
|
45
|
+
const select = target.querySelector('select')
|
46
|
+
|
47
|
+
select.setAttribute('name', '')
|
48
|
+
}
|
49
|
+
|
50
|
+
validateTarget(target) {
|
51
|
+
const select = target.querySelector('select')
|
52
|
+
const validName = select.getAttribute('valid-name')
|
53
|
+
|
54
|
+
select.setAttribute('name', validName)
|
55
|
+
}
|
56
|
+
|
57
|
+
enableType(type) {
|
58
|
+
const target = this.typeTargets.find((typeTarget) => typeTarget.dataset.type === type)
|
59
|
+
|
60
|
+
if (target) {
|
61
|
+
target.classList.remove('hidden')
|
62
|
+
this.validateTarget(target)
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
data/db/factories.rb
CHANGED
@@ -40,4 +40,8 @@ FactoryBot.define do
|
|
40
40
|
meta { [{foo: "bar", hey: "hi"}, {bar: "baz"}, {hoho: "hohoho"}].sample }
|
41
41
|
progress { Faker::Number.between(from: 0, to: 100) }
|
42
42
|
end
|
43
|
+
|
44
|
+
factory :comment do
|
45
|
+
body { Faker::Lorem.paragraphs(number: rand(4...10)).join("\n") }
|
46
|
+
end
|
43
47
|
end
|
data/lib/avo/base_resource.rb
CHANGED
@@ -22,6 +22,7 @@ module Avo
|
|
22
22
|
class_attribute :fields
|
23
23
|
class_attribute :grid_loader
|
24
24
|
class_attribute :visible_on_sidebar, default: true
|
25
|
+
class_attribute :unscoped_queries_on_index, default: false
|
25
26
|
|
26
27
|
class << self
|
27
28
|
def grid(&block)
|
@@ -87,20 +88,30 @@ module Avo
|
|
87
88
|
end
|
88
89
|
|
89
90
|
def get_fields(panel: nil, reflection: nil)
|
90
|
-
fields = get_field_definitions
|
91
|
-
field
|
92
|
-
|
91
|
+
fields = get_field_definitions
|
92
|
+
.select do |field|
|
93
|
+
field.send("show_on_#{@view}")
|
94
|
+
end
|
93
95
|
.select do |field|
|
94
|
-
|
95
|
-
|
96
|
+
field.visible?
|
97
|
+
end
|
96
98
|
.select do |field|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
99
|
+
# Strip out the reflection field in index queries with a parent association.
|
100
|
+
if reflection.present? &&
|
101
|
+
reflection.options.present? &&
|
102
|
+
field.respond_to?(:polymorphic_as) &&
|
103
|
+
field.polymorphic_as.to_s == reflection.options[:as].to_s
|
104
|
+
next
|
105
|
+
end
|
106
|
+
if field.respond_to?(:foreign_key) &&
|
107
|
+
reflection.present? &&
|
108
|
+
reflection.respond_to?(:foreign_key) &&
|
109
|
+
reflection.foreign_key != field.foreign_key
|
110
|
+
next
|
111
|
+
end
|
112
|
+
|
101
113
|
true
|
102
114
|
end
|
103
|
-
end
|
104
115
|
|
105
116
|
if panel.present?
|
106
117
|
fields = fields.select do |field|
|
@@ -216,28 +227,6 @@ module Avo
|
|
216
227
|
self.class.context
|
217
228
|
end
|
218
229
|
|
219
|
-
def query_search(via_resource_name:, via_resource_id:, user:, query: "")
|
220
|
-
# model_class = self.model
|
221
|
-
|
222
|
-
db_query = AuthorizationService.apply_policy(user, model_class)
|
223
|
-
|
224
|
-
if via_resource_name.present?
|
225
|
-
related_model = App.get_resource_by_name(via_resource_name).model
|
226
|
-
|
227
|
-
db_query = related_model.find(via_resource_id).public_send(plural_name.downcase)
|
228
|
-
end
|
229
|
-
|
230
|
-
new_query = []
|
231
|
-
|
232
|
-
[search].flatten.each_with_index do |search_by, index|
|
233
|
-
new_query.push "or" if index != 0
|
234
|
-
|
235
|
-
new_query.push "text(#{search_by}) ILIKE '%#{query}%'"
|
236
|
-
end
|
237
|
-
|
238
|
-
db_query.where(new_query.join(" "))
|
239
|
-
end
|
240
|
-
|
241
230
|
def attached_file_fields
|
242
231
|
get_field_definitions.select do |field|
|
243
232
|
[Avo::Fields::FileField, Avo::Fields::FilesField].include? field.class
|
@@ -250,14 +239,17 @@ module Avo
|
|
250
239
|
.reject do |field|
|
251
240
|
field.computed
|
252
241
|
end
|
253
|
-
.map
|
242
|
+
.map do |field|
|
243
|
+
[field.database_id(model).to_s, field]
|
244
|
+
end
|
245
|
+
.to_h
|
254
246
|
|
255
247
|
params.each do |key, value|
|
256
248
|
field = fields_by_database_id[key]
|
257
249
|
|
258
250
|
next unless field.present?
|
259
251
|
|
260
|
-
model = field.fill_field model, key, value
|
252
|
+
model = field.fill_field model, key, value, params
|
261
253
|
end
|
262
254
|
|
263
255
|
model
|
@@ -295,19 +287,22 @@ module Avo
|
|
295
287
|
|
296
288
|
# We will not overwrite any attributes that come pre-filled in the model.
|
297
289
|
def hydrate_model_with_default_values
|
298
|
-
default_values = get_fields
|
299
|
-
|
300
|
-
|
290
|
+
default_values = get_fields
|
291
|
+
.select do |field|
|
292
|
+
!field.computed
|
293
|
+
end
|
301
294
|
.map do |field|
|
302
295
|
id = field.id
|
303
296
|
value = field.value
|
304
297
|
|
305
|
-
if field.
|
298
|
+
if field.type == "belongs_to"
|
306
299
|
id = field.foreign_key.to_sym
|
307
300
|
|
308
301
|
reflection = @model._reflections[@params[:via_relation]]
|
309
302
|
|
310
|
-
if
|
303
|
+
if field.polymorphic_as.present? && field.types.map(&:to_s).include?(@params["via_relation_class"])
|
304
|
+
value = @params["via_relation_class"].safe_constantize.find(@params[:via_resource_id])
|
305
|
+
elsif reflection.present? && reflection.foreign_key.present? && field.id.to_s == @params[:via_relation].to_s
|
311
306
|
value = @params[:via_resource_id]
|
312
307
|
end
|
313
308
|
end
|
@@ -316,8 +311,8 @@ module Avo
|
|
316
311
|
end
|
317
312
|
.to_h
|
318
313
|
.select do |id, value|
|
319
|
-
|
320
|
-
|
314
|
+
value.present?
|
315
|
+
end
|
321
316
|
|
322
317
|
default_values.each do |id, value|
|
323
318
|
if @model.send(id).nil?
|
@@ -91,9 +91,11 @@ module Avo
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
def value
|
94
|
+
def value(property = nil)
|
95
|
+
property ||= id
|
96
|
+
|
95
97
|
# Get model value
|
96
|
-
final_value = @model.send(
|
98
|
+
final_value = @model.send(property) if (model_or_class(@model) == "model") && @model.respond_to?(property)
|
97
99
|
|
98
100
|
if (@view === :new) || @action.present?
|
99
101
|
final_value = if default.present? && default.respond_to?(:call)
|
@@ -114,7 +116,7 @@ module Avo
|
|
114
116
|
final_value
|
115
117
|
end
|
116
118
|
|
117
|
-
def fill_field(model, key, value)
|
119
|
+
def fill_field(model, key, value, params)
|
118
120
|
return model unless model.methods.include? key.to_sym
|
119
121
|
|
120
122
|
model.send("#{key}=", value)
|