avo 2.9.2.pre1 → 2.10.3.pre.1
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 +69 -69
- 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/country_field/edit_component.html.erb +9 -3
- data/app/components/avo/fields/date_field/edit_component.html.erb +26 -7
- data/app/components/avo/fields/date_field/index_component.html.erb +7 -1
- data/app/components/avo/fields/date_field/show_component.html.erb +7 -1
- data/app/components/avo/fields/date_time_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/edit_component.rb +5 -0
- data/app/components/avo/fields/file_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/files_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/select_field/edit_component.html.erb +14 -10
- data/app/components/avo/fields/show_component.rb +1 -1
- data/app/components/avo/index/ordering/button_component.rb +1 -15
- 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 +2 -2
- 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 +33 -10
- data/app/controllers/avo/base_controller.rb +11 -3
- data/app/controllers/avo/reorder_controller.rb +25 -0
- data/app/helpers/avo/application_helper.rb +6 -6
- data/app/helpers/avo/url_helpers.rb +1 -5
- data/app/javascript/avo.js +5 -1
- data/app/javascript/js/controllers/fields/date_field_controller.js +15 -3
- data/app/javascript/js/controllers/loading_button_controller.js +25 -21
- data/app/javascript/js/controllers/search_controller.js +3 -0
- 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 +5 -4
- data/db/factories.rb +1 -0
- data/lib/avo/app.rb +12 -7
- data/lib/avo/base_action.rb +2 -19
- data/lib/avo/base_card.rb +1 -7
- data/lib/avo/base_resource.rb +6 -98
- data/lib/avo/base_resource_tool.rb +3 -1
- data/lib/avo/concerns/has_fields.rb +249 -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/configuration.rb +2 -12
- 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 +21 -2
- data/lib/avo/fields/country_field.rb +2 -0
- data/lib/avo/fields/date_field.rb +13 -9
- data/lib/avo/fields/field_extensions/has_include_blank.rb +17 -0
- data/lib/avo/fields/field_extensions/visible_in_different_views.rb +18 -1
- data/lib/avo/fields/file_field.rb +2 -0
- data/lib/avo/fields/files_field.rb +2 -0
- data/lib/avo/fields/has_base_field.rb +20 -1
- data/lib/avo/fields/has_one_field.rb +4 -1
- data/lib/avo/fields/key_value_field.rb +4 -4
- data/lib/avo/fields/select_field.rb +2 -0
- data/lib/avo/grid_collector.rb +6 -3
- data/lib/avo/items_holder.rb +68 -0
- data/lib/avo/licensing/h_q.rb +12 -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 +75 -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/action_generator.rb +3 -2
- data/lib/generators/avo/base_generator.rb +14 -0
- data/lib/generators/avo/card/chartkick_generator.rb +18 -0
- data/lib/generators/avo/card/metric_generator.rb +18 -0
- data/lib/generators/avo/card/partial_generator.rb +19 -0
- data/lib/generators/avo/controller_generator.rb +9 -3
- data/lib/generators/avo/dashboard_generator.rb +2 -2
- data/lib/generators/avo/eject_generator.rb +2 -3
- data/lib/generators/avo/field_generator.rb +2 -2
- data/lib/generators/avo/filter_generator.rb +3 -2
- data/lib/generators/avo/install_generator.rb +2 -2
- data/lib/generators/avo/locales_generator.rb +2 -2
- data/lib/generators/avo/named_base_generator.rb +14 -0
- data/lib/generators/avo/resource_generator.rb +2 -2
- data/lib/generators/avo/resource_tool_generator.rb +4 -4
- 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/lib/generators/avo/tool_generator.rb +4 -4
- data/lib/generators/avo/version_generator.rb +23 -0
- data/public/avo-assets/avo.css +31 -3
- data/public/avo-assets/avo.js +72 -72
- data/public/avo-assets/avo.js.map +3 -3
- metadata +32 -16
- 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/fields/currency_field.rb +0 -15
- data/lib/generators/avo/chartkick_card_generator.rb +0 -16
- data/lib/generators/avo/metric_card_generator.rb +0 -16
- data/lib/generators/avo/partial_card_generator.rb +0 -17
@@ -4,88 +4,287 @@ 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.respond_to?(:foreign_key) &&
|
187
|
+
reflection.inverse_of.foreign_key == field.foreign_key
|
188
|
+
is_valid = false
|
189
|
+
end
|
76
190
|
|
77
|
-
|
78
|
-
|
79
|
-
|
191
|
+
# polymorphic association
|
192
|
+
if field.respond_to?(:foreign_key) &&
|
193
|
+
field.is_polymorphic? &&
|
194
|
+
reflection.respond_to?(:polymorphic?) &&
|
195
|
+
reflection.inverse_of.respond_to?(:foreign_key) &&
|
196
|
+
reflection.inverse_of.foreign_key == field.reflection.foreign_key
|
197
|
+
is_valid = false
|
198
|
+
end
|
199
|
+
end
|
80
200
|
end
|
201
|
+
|
202
|
+
is_valid
|
203
|
+
end
|
204
|
+
|
205
|
+
if panel.present?
|
206
|
+
fields = fields.select do |field|
|
207
|
+
field.panel_name == panel
|
81
208
|
end
|
82
209
|
end
|
83
210
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
211
|
+
hydrate_fields(model: @model, view: @view)
|
212
|
+
|
213
|
+
fields
|
214
|
+
end
|
215
|
+
|
216
|
+
def get_field(id)
|
217
|
+
get_field_definitions.find do |f|
|
218
|
+
f.id == id.to_sym
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def tools
|
223
|
+
check_license
|
224
|
+
|
225
|
+
return [] if App.license.lacks_with_trial :resource_tools
|
226
|
+
return [] if self.class.tools.blank?
|
227
|
+
|
228
|
+
self.items
|
229
|
+
.select do |item|
|
230
|
+
next if item.nil?
|
231
|
+
|
232
|
+
item.is_tool?
|
88
233
|
end
|
234
|
+
.map do |tool|
|
235
|
+
tool.hydrate view: view
|
236
|
+
tool
|
237
|
+
end
|
238
|
+
.select do |item|
|
239
|
+
item.visible_on?(view)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# Separates the fields that are in a panel and those that are just hanging out.
|
244
|
+
# Take the ones that aren't placed into a panel and add them to the "default" panel.
|
245
|
+
# This is to keep compatibility with the versions before 2.10 when you didn't have the ability to add fields to panels.
|
246
|
+
def get_items
|
247
|
+
panelless_items = []
|
248
|
+
panelfull_items = []
|
249
|
+
|
250
|
+
items.each do |item|
|
251
|
+
# fields and tabs can be hidden on some views
|
252
|
+
if item.respond_to? :visible_on?
|
253
|
+
next unless item.visible_on?(view)
|
254
|
+
end
|
255
|
+
if item.respond_to? :visible?
|
256
|
+
next unless item.visible?
|
257
|
+
end
|
258
|
+
|
259
|
+
if item.is_field?
|
260
|
+
if item.has_own_panel?
|
261
|
+
panelfull_items << item
|
262
|
+
else
|
263
|
+
panelless_items << item
|
264
|
+
end
|
265
|
+
else
|
266
|
+
panelfull_items << item
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Add all the panelles fields to a new panel
|
271
|
+
main_panel_holder = Avo::ItemsHolder.new
|
272
|
+
main_panel_holder.items = panelless_items
|
273
|
+
|
274
|
+
# Add that panel to the main panel
|
275
|
+
main_panel = Avo::MainPanel.new
|
276
|
+
main_panel.items_holder = main_panel_holder
|
277
|
+
|
278
|
+
# Return all the items but this time with all the panelless ones inside the main panel
|
279
|
+
[main_panel, *panelfull_items]
|
280
|
+
end
|
281
|
+
|
282
|
+
private
|
283
|
+
|
284
|
+
def check_license
|
285
|
+
if !Rails.env.production? && App.license.present? && App.license.lacks(:resource_tools)
|
286
|
+
# Add error message to let the developer know the resource tool will not be available in a production environment.
|
287
|
+
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
288
|
end
|
90
289
|
end
|
91
290
|
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
|
data/lib/avo/configuration.rb
CHANGED
@@ -40,7 +40,7 @@ module Avo
|
|
40
40
|
@per_page = 24
|
41
41
|
@per_page_steps = [12, 24, 48, 72]
|
42
42
|
@via_per_page = 8
|
43
|
-
@locale =
|
43
|
+
@locale = nil
|
44
44
|
@currency = "USD"
|
45
45
|
@default_view_type = :table
|
46
46
|
@license = "community"
|
@@ -78,16 +78,6 @@ module Avo
|
|
78
78
|
@profile_menu = nil
|
79
79
|
end
|
80
80
|
|
81
|
-
def locale_tag
|
82
|
-
::ISO::Tag.new(locale)
|
83
|
-
end
|
84
|
-
|
85
|
-
def language_code
|
86
|
-
locale_tag.language.code
|
87
|
-
rescue
|
88
|
-
"en"
|
89
|
-
end
|
90
|
-
|
91
81
|
def current_user_method(&block)
|
92
82
|
@current_user = block if block.present?
|
93
83
|
end
|
@@ -123,7 +113,7 @@ module Avo
|
|
123
113
|
end
|
124
114
|
|
125
115
|
def computed_root_path
|
126
|
-
Avo
|
116
|
+
Avo.configuration.root_path
|
127
117
|
end
|
128
118
|
|
129
119
|
def feature_enabled?(feature)
|
@@ -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
|
@@ -4,8 +4,11 @@ module Avo
|
|
4
4
|
extend ActiveSupport::DescendantsTracker
|
5
5
|
extend Avo::Fields::FieldExtensions::HasFieldName
|
6
6
|
|
7
|
-
include Avo::
|
7
|
+
include Avo::Concerns::IsResourceItem
|
8
|
+
include Avo::Concerns::HandlesFieldArgs
|
9
|
+
|
8
10
|
include ActionView::Helpers::UrlHelper
|
11
|
+
include Avo::Fields::FieldExtensions::VisibleInDifferentViews
|
9
12
|
|
10
13
|
include Avo::Concerns::HandlesFieldArgs
|
11
14
|
include Avo::Concerns::HasHTMLAttributes
|
@@ -48,8 +51,9 @@ module Avo
|
|
48
51
|
attr_reader :panel_name
|
49
52
|
|
50
53
|
class_attribute :field_name_attribute
|
54
|
+
class_attribute :item_type, default: :field
|
51
55
|
|
52
|
-
def initialize(id,
|
56
|
+
def initialize(id, **args, &block)
|
53
57
|
super(id, **args, &block)
|
54
58
|
|
55
59
|
@id = id
|
@@ -72,6 +76,8 @@ module Avo
|
|
72
76
|
@index_text_align = args[:index_text_align] || :left
|
73
77
|
@html = args[:html] || nil
|
74
78
|
|
79
|
+
@args = args
|
80
|
+
|
75
81
|
@updatable = true
|
76
82
|
@computable = true
|
77
83
|
@computed = block.present?
|
@@ -206,9 +212,14 @@ module Avo
|
|
206
212
|
|
207
213
|
# Try and build the component class or fallback to a blank one
|
208
214
|
def component_for_view(view = :index)
|
215
|
+
# Use the edit variant for all "update" views
|
216
|
+
view = :edit if view.in? [:new, :create, :update]
|
217
|
+
|
209
218
|
component_class = "::Avo::Fields::#{view_component_name}::#{view.to_s.camelize}Component"
|
210
219
|
component_class.constantize
|
211
220
|
rescue
|
221
|
+
# When returning nil, a race condition happens and throws an error in some environments.
|
222
|
+
# See https://github.com/avo-hq/avo/pull/365
|
212
223
|
::Avo::BlankFieldComponent
|
213
224
|
end
|
214
225
|
|
@@ -228,6 +239,14 @@ module Avo
|
|
228
239
|
true
|
229
240
|
end
|
230
241
|
|
242
|
+
def visible_in_reflection?
|
243
|
+
true
|
244
|
+
end
|
245
|
+
|
246
|
+
def hidden_in_reflection?
|
247
|
+
!visible_in_reflection?
|
248
|
+
end
|
249
|
+
|
231
250
|
private
|
232
251
|
|
233
252
|
def model_or_class(model)
|
@@ -3,26 +3,30 @@ module Avo
|
|
3
3
|
class DateField < TextField
|
4
4
|
attr_reader :first_day_of_week
|
5
5
|
attr_reader :picker_format
|
6
|
+
attr_reader :disable_mobile
|
6
7
|
attr_reader :format
|
7
8
|
attr_reader :relative
|
8
9
|
|
9
10
|
def initialize(id, **args, &block)
|
10
11
|
super(id, **args, &block)
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
add_string_prop args, :first_day_of_week, 0
|
14
|
+
add_string_prop args, :picker_format, "Y-m-d"
|
15
|
+
add_string_prop args, :format, "yyyy-LL-dd"
|
16
|
+
add_boolean_prop args, :relative
|
17
|
+
add_boolean_prop args, :disable_mobile
|
16
18
|
end
|
17
19
|
|
18
20
|
def formatted_value
|
19
21
|
return if value.blank?
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
value.iso8601
|
24
|
+
end
|
25
|
+
|
26
|
+
def edit_formatted_value
|
27
|
+
return nil if value.nil?
|
28
|
+
|
29
|
+
value.iso8601
|
26
30
|
end
|
27
31
|
end
|
28
32
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Avo
|
2
|
+
module Fields
|
3
|
+
module FieldExtensions
|
4
|
+
module HasIncludeBlank
|
5
|
+
def include_blank
|
6
|
+
if @args[:include_blank] == true
|
7
|
+
placeholder || '—'
|
8
|
+
elsif @args[:include_blank] == false
|
9
|
+
false
|
10
|
+
else
|
11
|
+
@args[:include_blank]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|