avo 3.1.0 → 3.1.2
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 +1 -1
- data/app/assets/builds/avo.base.css +703 -324
- data/app/assets/builds/avo.base.js +923 -7413
- data/app/assets/builds/avo.base.js.map +3 -3
- data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +106 -121
- data/app/components/avo/fields/belongs_to_field/edit_component.rb +18 -0
- data/app/components/avo/fields/has_one_field/show_component.rb +1 -0
- data/lib/avo/dynamic_router.rb +5 -29
- data/lib/avo/resources/resource_manager.rb +16 -24
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +0 -10
- metadata +2 -2
@@ -1,137 +1,122 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
data-reload-belongs-to-field-polymorphic-value="<%= is_polymorphic? %>"
|
4
|
-
data-reload-belongs-to-field-searchable-value="<%= @field.is_searchable? %>"
|
5
|
-
data-reload-belongs-to-field-relation-name-value="<%= @field.id %>"
|
6
|
-
data-reload-belongs-to-field-target-name-value="<%= form.object_name %>[<%= @field.id_input_foreign_key %>]"
|
7
|
-
>
|
8
|
-
<% if is_polymorphic? %>
|
9
|
-
<%
|
10
|
-
# Set the model keys so we can pass them over
|
11
|
-
model_keys = @field.types.map do |type|
|
12
|
-
resource = Avo.resource_manager.get_resource_by_model_class(type.to_s)
|
13
|
-
[type.to_s, resource.model_key]
|
14
|
-
end.to_h
|
15
|
-
%>
|
16
|
-
<div class="divide-y"
|
1
|
+
<% if is_polymorphic? %>
|
2
|
+
<div class="divide-y"
|
17
3
|
data-controller="belongs-to-field"
|
18
4
|
data-searchable="<%= @field.is_searchable? %>"
|
19
5
|
data-association="<%= @field.id %>"
|
20
6
|
data-association-class="<%= @field&.target_resource&.model_class || nil %>"
|
21
7
|
>
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
8
|
+
<%= field_wrapper **field_wrapper_args, help: @field.polymorphic_help || '' do %>
|
9
|
+
<%= @form.select @field.type_input_foreign_key, @field.types.map { |type| [Avo.resource_manager.get_resource_by_model_class(type.to_s).name, type.to_s] },
|
10
|
+
{
|
11
|
+
value: @field.value,
|
12
|
+
include_blank: @field.placeholder,
|
13
|
+
},
|
14
|
+
{
|
15
|
+
class: classes("w-full"),
|
16
|
+
data: {
|
17
|
+
**@field.get_html(:data, view: view, element: :input),
|
18
|
+
action: "change->belongs-to-field#changeType #{field_html_action}",
|
19
|
+
'belongs-to-field-target': "select",
|
27
20
|
},
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
<%= @form.hidden_field @field.type_input_foreign_key %>
|
43
|
-
<% end %>
|
21
|
+
disabled: disabled
|
22
|
+
}
|
23
|
+
%>
|
24
|
+
<%
|
25
|
+
# If the select field is disabled, no value will be sent. It's how HTML works.
|
26
|
+
# Thus the extra hidden field to actually send the related id to the server.
|
27
|
+
if disabled %>
|
28
|
+
<%= @form.hidden_field @field.type_input_foreign_key %>
|
44
29
|
<% end %>
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
30
|
+
<% end %>
|
31
|
+
<% @field.types.each do |type| %>
|
32
|
+
<div class="hidden"
|
33
|
+
data-belongs-to-field-target="type"
|
34
|
+
data-type="<%= type %>"
|
35
|
+
>
|
36
|
+
<%= field_wrapper **field_wrapper_args.merge!(data: reload_data), label: Avo.resource_manager.get_resource_by_model_class(type.to_s).name do %>
|
37
|
+
<% if @field.is_searchable? %>
|
38
|
+
<%= render Avo::Pro::SearchableAssociations::AutocompleteComponent.new form: @form,
|
39
|
+
disabled: disabled,
|
40
|
+
field: @field,
|
41
|
+
foreign_key: @field.id_input_foreign_key,
|
42
|
+
model_key: model_keys[type.to_s],
|
43
|
+
polymorphic_record: polymorphic_record,
|
44
|
+
resource: @resource,
|
45
|
+
style: @field.get_html(:style, view: view, element: :input),
|
46
|
+
type: type,
|
47
|
+
classes: classes("w-full"),
|
48
|
+
view: view
|
49
|
+
%>
|
50
|
+
<% else %>
|
51
|
+
<%= @form.select @field.id_input_foreign_key,
|
52
|
+
options_for_select(@field.values_for_type(type), @resource.present? && @resource.record.present? ? @resource.record[@field.id_input_foreign_key] : nil),
|
53
|
+
{
|
54
|
+
value: @resource.record[@field.id_input_foreign_key].to_s,
|
55
|
+
include_blank: @field.placeholder,
|
56
|
+
},
|
57
|
+
{
|
58
|
+
class: classes("w-full"),
|
59
|
+
data: @field.get_html(:data, view: view, element: :input),
|
60
|
+
disabled: disabled
|
61
|
+
}
|
62
|
+
%>
|
63
|
+
<%
|
64
|
+
# If the select field is disabled, no value will be sent. It's how HTML works.
|
65
|
+
# Thus the extra hidden field to actually send the related id to the server.
|
66
|
+
if disabled %>
|
67
|
+
<%= @form.hidden_field @field.id_input_foreign_key %>
|
83
68
|
<% end %>
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
69
|
+
<% end %>
|
70
|
+
<% if field.can_create? %>
|
71
|
+
<% create_href = create_path(Avo.resource_manager.get_resource_by_model_class(type.to_s)) %>
|
72
|
+
<% if !disabled && create_href.present? %>
|
73
|
+
<%= link_to t("avo.create_new_item", item: type.to_s.downcase),
|
74
|
+
create_href,
|
75
|
+
class: "text-sm"
|
76
|
+
%>
|
92
77
|
<% end %>
|
93
78
|
<% end %>
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
79
|
+
<% end %>
|
80
|
+
</div>
|
81
|
+
<% end %>
|
82
|
+
</div>
|
83
|
+
<% else %>
|
84
|
+
<%= field_wrapper **field_wrapper_args.merge!(data: reload_data) do %>
|
85
|
+
<% if @field.is_searchable? %>
|
86
|
+
<%= render Avo::Pro::SearchableAssociations::AutocompleteComponent.new form: @form,
|
87
|
+
field: @field,
|
88
|
+
model_key: @field.target_resource&.model_key,
|
89
|
+
foreign_key: @field.id_input_foreign_key,
|
90
|
+
resource: @resource,
|
91
|
+
disabled: disabled,
|
92
|
+
classes: classes("w-full"),
|
93
|
+
view: view,
|
94
|
+
style: @field.get_html(:style, view: view, element: :input)
|
95
|
+
%>
|
96
|
+
<% else %>
|
97
|
+
<%= @form.select @field.id_input_foreign_key, @field.options,
|
98
|
+
{
|
99
|
+
include_blank: @field.placeholder,
|
100
|
+
value: @field.value
|
101
|
+
},
|
102
|
+
{
|
103
|
+
class: classes("w-full"),
|
104
|
+
data: @field.get_html(:data, view: view, element: :input),
|
105
105
|
disabled: disabled,
|
106
|
-
classes: classes("w-full"),
|
107
|
-
view: view,
|
108
106
|
style: @field.get_html(:style, view: view, element: :input)
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
{
|
117
|
-
class: classes("w-full"),
|
118
|
-
data: @field.get_html(:data, view: view, element: :input),
|
119
|
-
disabled: disabled,
|
120
|
-
style: @field.get_html(:style, view: view, element: :input)
|
121
|
-
}
|
122
|
-
%>
|
123
|
-
<%
|
124
|
-
# If the select field is disabled, no value will be sent. It's how HTML works.
|
125
|
-
# Thus the extra hidden field to actually send the related id to the server.
|
126
|
-
if disabled %>
|
127
|
-
<%= @form.hidden_field @field.id_input_foreign_key %>
|
128
|
-
<% end %>
|
107
|
+
}
|
108
|
+
%>
|
109
|
+
<%
|
110
|
+
# If the select field is disabled, no value will be sent. It's how HTML works.
|
111
|
+
# Thus the extra hidden field to actually send the related id to the server.
|
112
|
+
if disabled %>
|
113
|
+
<%= @form.hidden_field @field.id_input_foreign_key %>
|
129
114
|
<% end %>
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
115
|
+
<% end %>
|
116
|
+
<% if field.can_create? %>
|
117
|
+
<% if !disabled && create_path.present? %>
|
118
|
+
<%= link_to t("avo.create_new_item", item: @field.name.downcase), create_path, class: "text-sm" %>
|
134
119
|
<% end %>
|
135
120
|
<% end %>
|
136
121
|
<% end %>
|
137
|
-
|
122
|
+
<% end %>
|
@@ -73,4 +73,22 @@ class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
|
|
73
73
|
def visit_through_association?
|
74
74
|
@field.target_resource.to_s == params[:via_resource_class].to_s
|
75
75
|
end
|
76
|
+
|
77
|
+
def model_keys
|
78
|
+
@field.types.map do |type|
|
79
|
+
resource = Avo.resource_manager.get_resource_by_model_class(type.to_s)
|
80
|
+
[type.to_s, resource.model_key]
|
81
|
+
end.to_h
|
82
|
+
end
|
83
|
+
|
84
|
+
def reload_data
|
85
|
+
{
|
86
|
+
controller: "reload-belongs-to-field",
|
87
|
+
action: 'turbo:before-stream-render@document->reload-belongs-to-field#beforeStreamRender',
|
88
|
+
reload_belongs_to_field_polymorphic_value: is_polymorphic?,
|
89
|
+
reload_belongs_to_field_searchable_value: @field.is_searchable?,
|
90
|
+
reload_belongs_to_field_relation_name_value: @field.id,
|
91
|
+
reload_belongs_to_field_target_name_value: "#{form.object_name}[#{@field.id_input_foreign_key}]"
|
92
|
+
}
|
93
|
+
end
|
76
94
|
end
|
@@ -41,6 +41,7 @@ class Avo::Fields::HasOneField::ShowComponent < Avo::Fields::ShowComponent
|
|
41
41
|
args = {
|
42
42
|
via_relation: association_id,
|
43
43
|
via_relation_class: @resource.model_class.to_s,
|
44
|
+
via_resource_class: @resource.class,
|
44
45
|
via_record_id: @resource.record.to_param,
|
45
46
|
via_association_type: :has_one
|
46
47
|
}
|
data/lib/avo/dynamic_router.rb
CHANGED
@@ -1,39 +1,15 @@
|
|
1
1
|
module Avo
|
2
2
|
class DynamicRouter
|
3
|
-
def self.eager_load(entity)
|
4
|
-
paths = Avo::ENTITIES.fetch entity
|
5
|
-
|
6
|
-
return unless paths.present?
|
7
|
-
|
8
|
-
pathname = Rails.root.join(*paths)
|
9
|
-
if pathname.directory?
|
10
|
-
Rails.autoloaders.main.eager_load_dir(pathname.to_s)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
3
|
def self.routes
|
15
4
|
Avo::Engine.routes.draw do
|
16
5
|
scope "resources", as: "resources" do
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
Avo::Resources::ResourceManager.fetch_resources
|
24
|
-
.select do |resource|
|
25
|
-
resource != :BaseResource
|
26
|
-
end
|
27
|
-
.select do |resource|
|
28
|
-
resource.is_a? Class
|
29
|
-
end
|
30
|
-
.map do |resource|
|
31
|
-
resources resource.route_key do
|
32
|
-
member do
|
33
|
-
get :preview
|
34
|
-
end
|
6
|
+
Avo::Resources::ResourceManager.fetch_resources.map do |resource|
|
7
|
+
resources resource.route_key do
|
8
|
+
member do
|
9
|
+
get :preview
|
35
10
|
end
|
36
11
|
end
|
12
|
+
end
|
37
13
|
end
|
38
14
|
end
|
39
15
|
end
|
@@ -8,7 +8,6 @@ module Avo
|
|
8
8
|
class << self
|
9
9
|
def build
|
10
10
|
instance = new
|
11
|
-
instance.init_resources
|
12
11
|
instance.check_bad_resources
|
13
12
|
instance
|
14
13
|
end
|
@@ -35,37 +34,30 @@ module Avo
|
|
35
34
|
# "FishResource",
|
36
35
|
# ]
|
37
36
|
def fetch_resources
|
38
|
-
|
39
|
-
|
37
|
+
if Avo.configuration.resources.present?
|
38
|
+
load_configured_resources
|
40
39
|
else
|
41
|
-
|
40
|
+
load_resources_namespace
|
42
41
|
end
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
43
|
+
BaseResource.descendants
|
44
|
+
end
|
45
|
+
|
46
|
+
def load_resources_namespace
|
47
|
+
Rails.autoloaders.main.eager_load_namespace(Avo::Resources)
|
48
|
+
end
|
49
|
+
|
50
|
+
def load_configured_resources
|
51
|
+
raise 'Resources configuration must be an array' unless Avo.configuration.resources.is_a? Array
|
52
|
+
|
53
|
+
Avo.configuration.resources.each do |resource|
|
54
|
+
resource.to_s.safe_constantize
|
50
55
|
end
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
54
59
|
def initialize
|
55
|
-
@resources =
|
56
|
-
end
|
57
|
-
|
58
|
-
def init_resources
|
59
|
-
self.resources = self.class.fetch_resources
|
60
|
-
.reject do |resource|
|
61
|
-
# Remove the BaseResource. We only need the descendants
|
62
|
-
resource == Avo::BaseResource
|
63
|
-
end
|
64
|
-
.uniq do |klass|
|
65
|
-
# On invalid resource configuration the resource classes get duplicated in `ObjectSpace`
|
66
|
-
# We need to de-duplicate them
|
67
|
-
klass.name
|
68
|
-
end
|
60
|
+
@resources = self.class.fetch_resources
|
69
61
|
end
|
70
62
|
|
71
63
|
def check_bad_resources
|
data/lib/avo/version.rb
CHANGED
data/lib/avo.rb
CHANGED
@@ -18,16 +18,6 @@ module Avo
|
|
18
18
|
IN_DEVELOPMENT = ENV["AVO_IN_DEVELOPMENT"] == "1"
|
19
19
|
PACKED = !IN_DEVELOPMENT
|
20
20
|
COOKIES_KEY = "avo"
|
21
|
-
ENTITIES = {
|
22
|
-
cards: ["app", "avo", "cards"],
|
23
|
-
scopes: ["app", "avo", "scopes"],
|
24
|
-
fields: ["app", "avo", "fields"],
|
25
|
-
filters: ["app", "avo", "filters"],
|
26
|
-
actions: ["app", "avo", "actions"],
|
27
|
-
resources: ["app", "avo", "resources"],
|
28
|
-
dashboards: ["app", "avo", "dashboards"],
|
29
|
-
resource_tools: ["app", "avo", "resource_tools"]
|
30
|
-
}
|
31
21
|
|
32
22
|
class LicenseVerificationTemperedError < StandardError; end
|
33
23
|
|
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: 3.1.
|
4
|
+
version: 3.1.2
|
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: 2023-12-
|
12
|
+
date: 2023-12-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|