avo 2.9.2.pre1 → 2.10.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.lock +5 -7
- data/README.md +4 -0
- data/app/assets/stylesheets/css/buttons.css +4 -1
- data/app/components/avo/actions_component.rb +6 -2
- data/app/components/avo/base_component.rb +2 -0
- data/app/components/avo/button_component.rb +3 -1
- data/app/components/avo/fields/common/key_value_component.html.erb +2 -2
- data/app/components/avo/fields/common/single_file_viewer_component.rb +1 -1
- data/app/components/avo/fields/date_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/date_time_field/edit_component.html.erb +10 -25
- data/app/components/avo/fields/date_time_field/index_component.html.erb +1 -9
- data/app/components/avo/fields/date_time_field/show_component.html.erb +1 -9
- data/app/components/avo/fields/edit_component.rb +5 -0
- data/app/components/avo/fields/show_component.rb +1 -1
- data/app/components/avo/index/ordering/button_component.rb +2 -12
- data/app/components/avo/index/resource_controls_component.html.erb +2 -2
- data/app/components/avo/index/resource_controls_component.rb +5 -1
- data/app/components/avo/index/resource_table_component.html.erb +1 -1
- data/app/components/avo/index/table_row_component.html.erb +1 -1
- data/app/components/avo/item_switcher_component.html.erb +19 -0
- data/app/components/avo/item_switcher_component.rb +45 -0
- data/app/components/avo/panel_component.html.erb +23 -24
- data/app/components/avo/panel_component.rb +8 -5
- data/app/components/avo/tab_group_component.html.erb +53 -0
- data/app/components/avo/tab_group_component.rb +51 -0
- data/app/components/avo/tab_switcher_component.html.erb +21 -0
- data/app/components/avo/tab_switcher_component.rb +86 -0
- data/app/components/avo/views/resource_edit_component.html.erb +34 -56
- data/app/components/avo/views/resource_edit_component.rb +11 -1
- data/app/components/avo/views/resource_index_component.html.erb +1 -1
- data/app/components/avo/views/resource_index_component.rb +3 -3
- data/app/components/avo/views/resource_show_component.html.erb +58 -89
- data/app/components/avo/views/resource_show_component.rb +2 -2
- data/app/controllers/avo/actions_controller.rb +1 -1
- data/app/controllers/avo/application_controller.rb +20 -3
- data/app/helpers/avo/application_helper.rb +0 -6
- data/app/helpers/avo/url_helpers.rb +1 -1
- data/app/javascript/avo.js +5 -1
- data/app/javascript/js/controllers/fields/date_field_controller.js +25 -87
- data/app/javascript/js/controllers/loading_button_controller.js +25 -21
- data/app/javascript/js/controllers/tabs_controller.js +86 -0
- data/app/javascript/js/controllers.js +2 -0
- data/app/views/avo/base/index.html.erb +1 -1
- data/app/views/avo/base/show.html.erb +1 -1
- data/app/views/avo/cards/show.html.erb +1 -1
- data/app/views/avo/debug/index.html.erb +1 -1
- data/app/views/avo/home/_actions.html.erb +1 -1
- data/app/views/avo/home/_dashboards.html.erb +19 -0
- data/app/views/avo/home/_filters.html.erb +1 -1
- data/app/views/avo/home/_resources.html.erb +1 -1
- data/app/views/avo/home/failed_to_load.html.erb +1 -1
- data/app/views/avo/home/index.html.erb +14 -2
- data/app/views/avo/partials/_javascript.html.erb +1 -1
- data/app/views/avo/partials/_tabs_toggle.html.erb +20 -0
- data/app/views/avo/private/design.html.erb +1 -1
- data/config/routes.rb +1 -1
- data/db/migrate/20210421064037_add_color_to_teams.rb +5 -0
- data/db/migrate/20210423075924_add_progress_to_projects.rb +5 -0
- data/db/migrate/20210525143134_add_slug_to_users.rb +6 -0
- data/lib/avo/app.rb +11 -4
- data/lib/avo/base_action.rb +2 -19
- data/lib/avo/base_card.rb +1 -7
- data/lib/avo/base_resource.rb +1 -95
- data/lib/avo/base_resource_tool.rb +3 -1
- data/lib/avo/concerns/handles_field_args.rb +1 -1
- data/lib/avo/concerns/has_fields.rb +247 -50
- data/lib/avo/concerns/has_html_attributes.rb +1 -1
- data/lib/avo/concerns/is_resource_item.rb +36 -0
- data/lib/avo/concerns/model_class_constantized.rb +23 -0
- data/lib/avo/dashboards/base_dashboard.rb +1 -1
- data/lib/avo/dsl/field_parser.rb +83 -0
- data/lib/avo/fields/base_field.rb +19 -2
- data/lib/avo/fields/date_field.rb +2 -0
- data/lib/avo/fields/date_time_field.rb +9 -21
- data/lib/avo/fields/field_extensions/visible_in_different_views.rb +18 -1
- data/lib/avo/fields/has_base_field.rb +20 -1
- data/lib/avo/fields/has_one_field.rb +4 -1
- data/lib/avo/grid_collector.rb +6 -3
- data/lib/avo/items_holder.rb +68 -0
- data/lib/avo/licensing/h_q.rb +10 -0
- data/lib/avo/main_panel.rb +3 -0
- data/lib/avo/menu/builder.rb +8 -7
- data/lib/avo/panel.rb +25 -0
- data/lib/avo/panel_builder.rb +23 -0
- data/lib/avo/services/uri_service.rb +71 -0
- data/lib/avo/tab.rb +78 -0
- data/lib/avo/tab_builder.rb +25 -0
- data/lib/avo/tab_group.rb +40 -0
- data/lib/avo/tab_group_builder.rb +43 -0
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +1 -0
- data/lib/generators/avo/templates/locales/avo.fr.yml +115 -0
- data/lib/generators/avo/templates/resource/controller.tt +2 -0
- data/lib/generators/avo/templates/resource_tools/partial.tt +1 -1
- data/lib/generators/avo/templates/tool/view.tt +1 -1
- data/public/avo-assets/avo.css +27 -3
- data/public/avo-assets/avo.js +77 -77
- data/public/avo-assets/avo.js.map +3 -3
- metadata +28 -13
- data/app/assets/builds/action_cable.js +0 -2
- data/app/assets/builds/action_cable.js.map +0 -7
- data/app/assets/builds/application.js +0 -2
- data/app/assets/builds/application.js.map +0 -7
- data/app/assets/builds/avo.css +0 -9028
- data/app/assets/builds/avo.js +0 -512
- data/app/assets/builds/avo.js.map +0 -7
- data/app/assets/builds/avo_custom.js +0 -6
- data/app/assets/builds/avo_custom.js.map +0 -7
- data/lib/avo/concerns/has_tools.rb +0 -47
data/lib/avo/base_resource.rb
CHANGED
@@ -4,10 +4,10 @@ module Avo
|
|
4
4
|
extend HasContext
|
5
5
|
|
6
6
|
include ActionView::Helpers::UrlHelper
|
7
|
-
include Avo::Concerns::HasTools
|
8
7
|
include Avo::Concerns::HasModel
|
9
8
|
include Avo::Concerns::HasFields
|
10
9
|
include Avo::Concerns::HasStimulusControllers
|
10
|
+
include Avo::Concerns::ModelClassConstantized
|
11
11
|
|
12
12
|
delegate :view_context, to: ::Avo::App
|
13
13
|
delegate :simple_format, :content_tag, to: :view_context
|
@@ -29,7 +29,6 @@ module Avo
|
|
29
29
|
class_attribute :search_query, default: nil
|
30
30
|
class_attribute :search_query_help, default: ""
|
31
31
|
class_attribute :includes, default: []
|
32
|
-
class_attribute :model_class
|
33
32
|
class_attribute :translation_key
|
34
33
|
class_attribute :default_view_type, default: :table
|
35
34
|
class_attribute :devise_password_optional, default: false
|
@@ -44,7 +43,6 @@ module Avo
|
|
44
43
|
class_attribute :hide_from_global_search, default: false
|
45
44
|
class_attribute :after_create_path, default: :show
|
46
45
|
class_attribute :after_update_path, default: :show
|
47
|
-
class_attribute :invalid_fields
|
48
46
|
class_attribute :record_selector, default: true
|
49
47
|
class_attribute :keep_filters_panel_open, default: false
|
50
48
|
|
@@ -123,80 +121,6 @@ module Avo
|
|
123
121
|
self
|
124
122
|
end
|
125
123
|
|
126
|
-
def get_field_definitions
|
127
|
-
return [] if self.class.fields.blank?
|
128
|
-
|
129
|
-
fields = self.class.fields.map do |field|
|
130
|
-
field.hydrate(resource: self, panel_name: default_panel_name, user: user)
|
131
|
-
end
|
132
|
-
|
133
|
-
if Avo::App.license.lacks_with_trial(:custom_fields)
|
134
|
-
fields = fields.reject do |field|
|
135
|
-
field.custom?
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
if Avo::App.license.lacks_with_trial(:advanced_fields)
|
140
|
-
fields = fields.reject do |field|
|
141
|
-
field.type == "tags"
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
fields
|
146
|
-
end
|
147
|
-
|
148
|
-
def get_fields(panel: nil, reflection: nil)
|
149
|
-
fields = get_field_definitions
|
150
|
-
.select do |field|
|
151
|
-
field.send("show_on_#{@view}")
|
152
|
-
end
|
153
|
-
.select do |field|
|
154
|
-
field.visible?
|
155
|
-
end
|
156
|
-
.select do |field|
|
157
|
-
is_valid = true
|
158
|
-
|
159
|
-
# Strip out the reflection field in index queries with a parent association.
|
160
|
-
if reflection.present?
|
161
|
-
# regular non-polymorphic association
|
162
|
-
# we're matching the reflection inverse_of foriegn key with the field's foreign_key
|
163
|
-
if field.is_a?(Avo::Fields::BelongsToField)
|
164
|
-
if field.respond_to?(:foreign_key) &&
|
165
|
-
reflection.inverse_of.present? &&
|
166
|
-
reflection.inverse_of.foreign_key == field.foreign_key
|
167
|
-
is_valid = false
|
168
|
-
end
|
169
|
-
|
170
|
-
# polymorphic association
|
171
|
-
if field.respond_to?(:foreign_key) &&
|
172
|
-
field.is_polymorphic? &&
|
173
|
-
reflection.respond_to?(:polymorphic?) &&
|
174
|
-
reflection.inverse_of.foreign_key == field.reflection.foreign_key
|
175
|
-
is_valid = false
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
is_valid
|
181
|
-
end
|
182
|
-
|
183
|
-
if panel.present?
|
184
|
-
fields = fields.select do |field|
|
185
|
-
field.panel_name == panel
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
hydrate_fields(model: @model, view: @view)
|
190
|
-
|
191
|
-
fields
|
192
|
-
end
|
193
|
-
|
194
|
-
def get_field(id)
|
195
|
-
get_field_definitions.find do |f|
|
196
|
-
f.id == id.to_sym
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
124
|
def get_grid_fields
|
201
125
|
return if self.class.grid_loader.blank?
|
202
126
|
|
@@ -215,14 +139,6 @@ module Avo
|
|
215
139
|
self.class.actions_loader.bag
|
216
140
|
end
|
217
141
|
|
218
|
-
def hydrate_fields(model: nil, view: nil)
|
219
|
-
fields.map do |field|
|
220
|
-
field.hydrate(model: @model, view: @view, resource: self)
|
221
|
-
end
|
222
|
-
|
223
|
-
self
|
224
|
-
end
|
225
|
-
|
226
142
|
def default_panel_name
|
227
143
|
return @params[:related_name].capitalize if @params.present? && @params[:related_name].present?
|
228
144
|
|
@@ -236,16 +152,6 @@ module Avo
|
|
236
152
|
end
|
237
153
|
end
|
238
154
|
|
239
|
-
def panels
|
240
|
-
[
|
241
|
-
{
|
242
|
-
name: default_panel_name,
|
243
|
-
type: :fields,
|
244
|
-
in_panel: true
|
245
|
-
}
|
246
|
-
]
|
247
|
-
end
|
248
|
-
|
249
155
|
def class_name_without_resource
|
250
156
|
self.class.name.demodulize.chomp("Resource")
|
251
157
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module Avo
|
2
2
|
class BaseResourceTool
|
3
|
+
include Avo::Concerns::IsResourceItem
|
3
4
|
include Avo::Fields::FieldExtensions::VisibleInDifferentViews
|
4
5
|
|
5
6
|
class_attribute :name
|
6
7
|
class_attribute :partial
|
8
|
+
class_attribute :item_type, default: :tool
|
7
9
|
|
8
10
|
attr_accessor :params
|
9
11
|
attr_accessor :resource
|
@@ -20,7 +22,7 @@ module Avo
|
|
20
22
|
end
|
21
23
|
|
22
24
|
def hydrate(view: nil)
|
23
|
-
@view = view
|
25
|
+
@view = view if view.present?
|
24
26
|
|
25
27
|
self
|
26
28
|
end
|
@@ -28,7 +28,7 @@ module Avo
|
|
28
28
|
add_prop_from_args args, name: name, default: default, type: :array
|
29
29
|
end
|
30
30
|
|
31
|
-
def add_string_prop(args, name, default =
|
31
|
+
def add_string_prop(args, name, default = [])
|
32
32
|
add_prop_from_args args, name: name, default: default, type: :string
|
33
33
|
end
|
34
34
|
end
|
@@ -4,88 +4,285 @@ module Avo
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
class_attribute :
|
8
|
-
class_attribute :
|
7
|
+
class_attribute :items_holder
|
8
|
+
class_attribute :items_index, default: 0
|
9
|
+
class_attribute :tabs_holder
|
10
|
+
class_attribute :tabs_tabs_holder
|
11
|
+
class_attribute :raw_tabs
|
12
|
+
class_attribute :tools_holder
|
9
13
|
end
|
10
14
|
|
11
15
|
class_methods do
|
12
|
-
|
13
|
-
self.invalid_fields ||= []
|
16
|
+
delegate :tool, to: :items_holder
|
14
17
|
|
15
|
-
|
18
|
+
# DSL methods
|
19
|
+
def field(name, **args, &block)
|
20
|
+
ensure_items_holder_initialized
|
16
21
|
|
17
|
-
|
18
|
-
|
22
|
+
self.items_holder.field name, **args, &block
|
23
|
+
end
|
24
|
+
|
25
|
+
def panel(name = nil, **args, &block)
|
26
|
+
ensure_items_holder_initialized
|
27
|
+
|
28
|
+
self.items_holder.panel name, **args, &block
|
29
|
+
end
|
30
|
+
|
31
|
+
def tabs(&block)
|
32
|
+
ensure_items_holder_initialized
|
33
|
+
|
34
|
+
self.items_holder.tabs Avo::TabGroupBuilder.parse_block(&block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def heading(body, **args)
|
38
|
+
self.items_holder.add_item Avo::Fields::HeadingField.new(body, order_index: items_index, **args)
|
39
|
+
end
|
40
|
+
# END DSL methods
|
41
|
+
|
42
|
+
def items
|
43
|
+
if self.items_holder.present?
|
44
|
+
self.items_holder.items
|
19
45
|
else
|
20
|
-
|
21
|
-
name: field_name,
|
22
|
-
as: as,
|
23
|
-
resource: name,
|
24
|
-
message: "There's an invalid field configuration for this resource. <br/> <code class='px-1 py-px rounded bg-red-600'>field :#{field_name}, as: #{as}</code>"
|
25
|
-
})
|
46
|
+
[]
|
26
47
|
end
|
27
48
|
end
|
28
49
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
50
|
+
def tools
|
51
|
+
self.tools_holder
|
52
|
+
end
|
53
|
+
|
54
|
+
# Dives deep into panels and tabs to fetch all the fields for a resource.
|
55
|
+
def fields(only_root: false)
|
56
|
+
fields = []
|
57
|
+
|
58
|
+
self.items.each do |item|
|
59
|
+
next if item.nil?
|
60
|
+
|
61
|
+
unless only_root
|
62
|
+
# Dive into panels to fetch their fields
|
63
|
+
if item.is_panel?
|
64
|
+
fields << extract_fields_from_items(item)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Dive into tabs to fetch their fields
|
68
|
+
if item.is_tab_group?
|
69
|
+
item.items.map do |tab|
|
70
|
+
fields << extract_fields_from_items(tab)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
if item.is_field?
|
77
|
+
fields << item
|
78
|
+
end
|
35
79
|
end
|
80
|
+
|
81
|
+
fields.flatten
|
36
82
|
end
|
37
83
|
|
38
|
-
def
|
39
|
-
|
84
|
+
def tab_groups
|
85
|
+
self.items.select do |item|
|
86
|
+
item.instance_of? Avo::TabGroup
|
87
|
+
end
|
40
88
|
end
|
41
89
|
|
42
90
|
private
|
43
91
|
|
92
|
+
def extract_fields_from_items(thing)
|
93
|
+
fields = []
|
94
|
+
|
95
|
+
thing.items.each do |item|
|
96
|
+
if item.is_field?
|
97
|
+
fields << item
|
98
|
+
elsif item.is_panel?
|
99
|
+
fields << extract_fields_from_items(item)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
fields
|
104
|
+
end
|
105
|
+
|
106
|
+
def ensure_items_holder_initialized
|
107
|
+
self.items_holder ||= Avo::ItemsHolder.new
|
108
|
+
end
|
109
|
+
|
44
110
|
def add_to_fields(instance)
|
45
|
-
self.
|
46
|
-
self.
|
47
|
-
|
111
|
+
self.items ||= []
|
112
|
+
self.items << instance
|
113
|
+
increment_order_index
|
48
114
|
end
|
49
115
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
116
|
+
def increment_order_index
|
117
|
+
self.items_index += 1
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
delegate :invalid_fields, to: :items_holder
|
122
|
+
delegate :items, to: :items_holder
|
123
|
+
|
124
|
+
def hydrate_fields(model: nil, view: nil)
|
125
|
+
fields.map do |field|
|
126
|
+
field.hydrate(model: @model, view: @view, resource: self)
|
127
|
+
end
|
128
|
+
|
129
|
+
self
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_tabs
|
133
|
+
tabs_holder
|
134
|
+
end
|
135
|
+
|
136
|
+
def fields(**args)
|
137
|
+
self.class.fields(**args)
|
138
|
+
end
|
139
|
+
|
140
|
+
def tab_groups
|
141
|
+
self.class.tab_groups
|
142
|
+
end
|
143
|
+
|
144
|
+
def get_field_definitions(only_root: false)
|
145
|
+
fields = self.fields(only_root: only_root)
|
146
|
+
|
147
|
+
return [] if fields.blank?
|
148
|
+
|
149
|
+
items = fields.map do |field|
|
150
|
+
field.hydrate(resource: self, user: user, view: view)
|
56
151
|
end
|
57
152
|
|
58
|
-
|
59
|
-
|
60
|
-
field
|
153
|
+
if Avo::App.license.lacks_with_trial(:custom_fields)
|
154
|
+
items = items.reject do |field|
|
155
|
+
field.custom?
|
61
156
|
end
|
157
|
+
end
|
62
158
|
|
63
|
-
|
159
|
+
if Avo::App.license.lacks_with_trial(:advanced_fields)
|
160
|
+
items = items.reject do |field|
|
161
|
+
field.type == "tags"
|
162
|
+
end
|
64
163
|
end
|
65
164
|
|
66
|
-
|
67
|
-
|
165
|
+
items
|
166
|
+
end
|
68
167
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
168
|
+
def get_fields(panel: nil, reflection: nil, only_root: false)
|
169
|
+
fields = get_field_definitions(only_root: only_root)
|
170
|
+
.select do |field|
|
171
|
+
field.visible_on?(view)
|
172
|
+
end
|
173
|
+
.select do |field|
|
174
|
+
field.visible?
|
175
|
+
end
|
176
|
+
.select do |field|
|
177
|
+
is_valid = true
|
178
|
+
|
179
|
+
# Strip out the reflection field in index queries with a parent association.
|
180
|
+
if reflection.present?
|
181
|
+
# regular non-polymorphic association
|
182
|
+
# we're matching the reflection inverse_of foriegn key with the field's foreign_key
|
183
|
+
if field.is_a?(Avo::Fields::BelongsToField)
|
184
|
+
if field.respond_to?(:foreign_key) &&
|
185
|
+
reflection.inverse_of.present? &&
|
186
|
+
reflection.inverse_of.foreign_key == field.foreign_key
|
187
|
+
is_valid = false
|
188
|
+
end
|
76
189
|
|
77
|
-
|
78
|
-
|
79
|
-
|
190
|
+
# polymorphic association
|
191
|
+
if field.respond_to?(:foreign_key) &&
|
192
|
+
field.is_polymorphic? &&
|
193
|
+
reflection.respond_to?(:polymorphic?) &&
|
194
|
+
reflection.inverse_of.foreign_key == field.reflection.foreign_key
|
195
|
+
is_valid = false
|
196
|
+
end
|
197
|
+
end
|
80
198
|
end
|
199
|
+
|
200
|
+
is_valid
|
201
|
+
end
|
202
|
+
|
203
|
+
if panel.present?
|
204
|
+
fields = fields.select do |field|
|
205
|
+
field.panel_name == panel
|
81
206
|
end
|
82
207
|
end
|
83
208
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
209
|
+
hydrate_fields(model: @model, view: @view)
|
210
|
+
|
211
|
+
fields
|
212
|
+
end
|
213
|
+
|
214
|
+
def get_field(id)
|
215
|
+
get_field_definitions.find do |f|
|
216
|
+
f.id == id.to_sym
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def tools
|
221
|
+
check_license
|
222
|
+
|
223
|
+
return [] if App.license.lacks_with_trial :resource_tools
|
224
|
+
return [] if self.class.tools.blank?
|
225
|
+
|
226
|
+
self.items
|
227
|
+
.select do |item|
|
228
|
+
next if item.nil?
|
229
|
+
|
230
|
+
item.is_tool?
|
88
231
|
end
|
232
|
+
.map do |tool|
|
233
|
+
tool.hydrate view: view
|
234
|
+
tool
|
235
|
+
end
|
236
|
+
.select do |item|
|
237
|
+
item.visible_on?(view)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Separates the fields that are in a panel and those that are just hanging out.
|
242
|
+
# Take the ones that aren't placed into a panel and add them to the "default" panel.
|
243
|
+
# This is to keep compatibility with the versions before 2.10 when you didn't have the ability to add fields to panels.
|
244
|
+
def get_items
|
245
|
+
panelless_items = []
|
246
|
+
panelfull_items = []
|
247
|
+
|
248
|
+
items.each do |item|
|
249
|
+
# fields and tabs can be hidden on some views
|
250
|
+
if item.respond_to? :visible_on?
|
251
|
+
next unless item.visible_on?(view)
|
252
|
+
end
|
253
|
+
if item.respond_to? :visible?
|
254
|
+
next unless item.visible?
|
255
|
+
end
|
256
|
+
|
257
|
+
if item.is_field?
|
258
|
+
if item.has_own_panel?
|
259
|
+
panelfull_items << item
|
260
|
+
else
|
261
|
+
panelless_items << item
|
262
|
+
end
|
263
|
+
else
|
264
|
+
panelfull_items << item
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# Add all the panelles fields to a new panel
|
269
|
+
main_panel_holder = Avo::ItemsHolder.new
|
270
|
+
main_panel_holder.items = panelless_items
|
271
|
+
|
272
|
+
# Add that panel to the main panel
|
273
|
+
main_panel = Avo::MainPanel.new
|
274
|
+
main_panel.items_holder = main_panel_holder
|
275
|
+
|
276
|
+
# Return all the items but this time with all the panelless ones inside the main panel
|
277
|
+
[main_panel, *panelfull_items]
|
278
|
+
end
|
279
|
+
|
280
|
+
private
|
281
|
+
|
282
|
+
def check_license
|
283
|
+
if !Rails.env.production? && App.license.present? && App.license.lacks(:resource_tools)
|
284
|
+
# Add error message to let the developer know the resource tool will not be available in a production environment.
|
285
|
+
Avo::App.error_messages.push "Warning: Your license is invalid or doesn't support resource tools. The resource tools will not be visible in a production environment."
|
89
286
|
end
|
90
287
|
end
|
91
288
|
end
|
@@ -50,7 +50,7 @@ module Avo
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def add_default_data_attributes(attributes, name, element, view)
|
53
|
-
if !attributes.nil? && name == :data && element == :input && view.in?([:edit, :new]) && resource.present?
|
53
|
+
if !attributes.nil? && name == :data && element == :input && view.in?([:edit, :new]) && resource.present? && resource.respond_to?(:get_stimulus_controllers)
|
54
54
|
extra_attributes = resource.get_stimulus_controllers
|
55
55
|
.split(" ")
|
56
56
|
.map do |controller|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# This concern helps us figure out what kind of items (field, tool, tab_group, or panel) have been passed to the resource or action.
|
2
|
+
module Avo
|
3
|
+
module Concerns
|
4
|
+
module IsResourceItem
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :item_type, default: nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def is_field?
|
12
|
+
self.class.item_type == :field
|
13
|
+
end
|
14
|
+
|
15
|
+
def is_panel?
|
16
|
+
self.class.item_type == :panel || self.class.item_type == :main_panel
|
17
|
+
end
|
18
|
+
|
19
|
+
def is_main_panel?
|
20
|
+
self.class.item_type == :main_panel
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_tool?
|
24
|
+
self.class.item_type == :tool
|
25
|
+
end
|
26
|
+
|
27
|
+
def is_tab?
|
28
|
+
self.class.item_type == :tab
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_tab_group?
|
32
|
+
self.class.item_type == :tab_group
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Avo
|
2
|
+
module Concerns
|
3
|
+
module ModelClassConstantized
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
class_methods do
|
7
|
+
attr_reader :model_class
|
8
|
+
|
9
|
+
# Cast the model class to a constantized version and memoize it like that
|
10
|
+
def model_class=(value)
|
11
|
+
@model_class = case value
|
12
|
+
when Class
|
13
|
+
value
|
14
|
+
when String, Symbol
|
15
|
+
value.to_s.safe_constantize
|
16
|
+
else
|
17
|
+
raise ArgumentError.new "Failed to find a proper model class for #{self.to_s}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Avo
|
2
|
+
module Dsl
|
3
|
+
class FieldParser
|
4
|
+
attr_reader :as
|
5
|
+
attr_reader :args
|
6
|
+
attr_reader :id
|
7
|
+
attr_reader :block
|
8
|
+
attr_reader :instance
|
9
|
+
attr_reader :order_index
|
10
|
+
|
11
|
+
def initialize(id:, order_index: 0, **args, &block)
|
12
|
+
@id = id
|
13
|
+
@as = args.fetch(:as, nil)
|
14
|
+
@order_index = order_index
|
15
|
+
@args = args
|
16
|
+
@block = block
|
17
|
+
@instance = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
instance.present?
|
22
|
+
end
|
23
|
+
|
24
|
+
def invalid?
|
25
|
+
!valid?
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse
|
29
|
+
# The field is passed as a symbol eg: :text, :color_picker, :trix
|
30
|
+
@instance = if as.is_a? Symbol
|
31
|
+
parse_from_symbol
|
32
|
+
elsif as.is_a? Class
|
33
|
+
parse_from_class
|
34
|
+
end
|
35
|
+
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def parse_from_symbol
|
42
|
+
field_class = field_class_from_symbol(as)
|
43
|
+
|
44
|
+
if field_class.present?
|
45
|
+
# The field has been registered before.
|
46
|
+
instantiate_field(id, klass: field_class, **args, &block)
|
47
|
+
else
|
48
|
+
# The symbol can be transformed to a class and found.
|
49
|
+
class_name = as.to_s.camelize
|
50
|
+
field_class = "#{class_name}Field"
|
51
|
+
|
52
|
+
# Discover & load custom field classes
|
53
|
+
if Object.const_defined? field_class
|
54
|
+
instantiate_field(id, klass: field_class.safe_constantize, **args, &block)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def parse_from_class
|
60
|
+
# The field has been passed as a class.
|
61
|
+
if Object.const_defined? as.to_s
|
62
|
+
instantiate_field(id, klass: as, **args, &block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def instantiate_field(id, klass:, **args, &block)
|
67
|
+
if block
|
68
|
+
klass.new(id, **args || {}, &block)
|
69
|
+
else
|
70
|
+
klass.new(id, **args || {})
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def field_class_from_symbol(symbol)
|
75
|
+
matched_field = Avo::App.fields.find do |field|
|
76
|
+
field[:name].to_s == symbol.to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
return matched_field[:class] if matched_field.present? && matched_field[:class].present?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|