avo 3.0.0.pre13 → 3.0.0.pre15

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.

Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +2 -1
  4. data/app/components/avo/alert_component.html.erb +1 -1
  5. data/app/components/avo/base_component.rb +7 -7
  6. data/app/components/avo/field_wrapper_component.rb +1 -1
  7. data/app/components/avo/fields/area_field/edit_component.html.erb +1 -1
  8. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +5 -5
  9. data/app/components/avo/fields/belongs_to_field/edit_component.rb +4 -4
  10. data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -0
  11. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
  12. data/app/components/avo/fields/code_field/edit_component.html.erb +1 -0
  13. data/app/components/avo/fields/country_field/edit_component.html.erb +1 -0
  14. data/app/components/avo/fields/file_field/index_component.rb +2 -2
  15. data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -0
  16. data/app/components/avo/fields/index_component.rb +1 -0
  17. data/app/components/avo/fields/location_field/show_component.html.erb +1 -1
  18. data/app/components/avo/fields/markdown_field/edit_component.html.erb +1 -0
  19. data/app/components/avo/fields/number_field/edit_component.html.erb +1 -0
  20. data/app/components/avo/fields/password_field/edit_component.html.erb +1 -0
  21. data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +1 -0
  22. data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
  23. data/app/components/avo/fields/text_field/edit_component.html.erb +1 -1
  24. data/app/components/avo/fields/textarea_field/edit_component.html.erb +1 -0
  25. data/app/components/avo/fields/trix_field/edit_component.html.erb +2 -1
  26. data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
  27. data/app/components/avo/index/resource_controls_component.rb +6 -6
  28. data/app/components/avo/index/resource_table_component.rb +1 -1
  29. data/app/components/avo/item_switcher_component.html.erb +9 -4
  30. data/app/components/avo/item_switcher_component.rb +2 -1
  31. data/app/components/avo/resource_component.rb +5 -3
  32. data/app/components/avo/resource_sidebar_component.rb +1 -1
  33. data/app/components/avo/row_component.html.erb +3 -0
  34. data/app/components/avo/row_component.rb +12 -0
  35. data/app/components/avo/sidebar/link_component.html.erb +2 -0
  36. data/app/components/avo/sidebar/link_component.rb +5 -3
  37. data/app/components/avo/sidebar_component.html.erb +3 -3
  38. data/app/components/avo/sidebar_component.rb +4 -4
  39. data/app/components/avo/sidebar_profile_component.html.erb +4 -4
  40. data/app/components/avo/views/resource_edit_component.rb +1 -1
  41. data/app/components/avo/views/resource_index_component.html.erb +1 -1
  42. data/app/components/avo/views/resource_index_component.rb +8 -8
  43. data/app/controllers/avo/actions_controller.rb +5 -7
  44. data/app/controllers/avo/application_controller.rb +71 -66
  45. data/app/controllers/avo/associations_controller.rb +4 -6
  46. data/app/controllers/avo/attachments_controller.rb +1 -1
  47. data/app/controllers/avo/base_controller.rb +25 -25
  48. data/app/controllers/avo/home_controller.rb +1 -1
  49. data/app/controllers/avo/search_controller.rb +14 -12
  50. data/app/controllers/concerns/avo/initializes_avo.rb +3 -6
  51. data/app/javascript/js/controllers/fields/easy_mde_controller.js +1 -0
  52. data/app/views/avo/associations/new.html.erb +1 -1
  53. data/app/views/avo/debug/status.html.erb +1 -1
  54. data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
  55. data/app/views/avo/partials/_footer.html.erb +1 -1
  56. data/app/views/avo/partials/_javascript.html.erb +1 -1
  57. data/app/views/avo/partials/_navbar.html.erb +1 -1
  58. data/app/views/layouts/avo/application.html.erb +2 -2
  59. data/avo.gemspec +1 -0
  60. data/config/initializers/pagy.rb +12 -10
  61. data/config/routes.rb +3 -3
  62. data/db/factories.rb +2 -1
  63. data/lib/avo/base_action.rb +4 -2
  64. data/lib/avo/base_resource.rb +123 -92
  65. data/lib/avo/concerns/has_item_type.rb +4 -0
  66. data/lib/avo/concerns/has_items.rb +20 -15
  67. data/lib/avo/concerns/model_class_constantized.rb +0 -2
  68. data/lib/avo/current.rb +29 -2
  69. data/lib/avo/dsl/field_parser.rb +1 -1
  70. data/lib/avo/dynamic_router.rb +12 -1
  71. data/lib/avo/engine.rb +4 -7
  72. data/lib/avo/execution_context.rb +1 -1
  73. data/lib/avo/fields/base_field.rb +25 -3
  74. data/lib/avo/fields/belongs_to_field.rb +8 -7
  75. data/lib/avo/fields/concerns/is_searchable.rb +1 -1
  76. data/lib/avo/fields/concerns/use_resource.rb +1 -1
  77. data/lib/avo/fields/field_manager.rb +13 -3
  78. data/lib/avo/fields/has_base_field.rb +4 -4
  79. data/lib/avo/fields/has_one_field.rb +1 -1
  80. data/lib/avo/fields/location_field.rb +18 -1
  81. data/lib/avo/filters/base_filter.rb +3 -1
  82. data/lib/avo/html/builder.rb +3 -1
  83. data/lib/avo/licensing/h_q.rb +11 -6
  84. data/lib/avo/licensing/license.rb +1 -1
  85. data/lib/avo/licensing/license_manager.rb +1 -1
  86. data/lib/avo/licensing/{null_license.rb → nil_license.rb} +1 -1
  87. data/lib/avo/loaders/fields_loader.rb +7 -1
  88. data/lib/avo/plugin_manager.rb +2 -4
  89. data/lib/avo/reloader.rb +1 -1
  90. data/lib/avo/resources/items/holder.rb +5 -1
  91. data/lib/avo/resources/items/item_group.rb +1 -0
  92. data/lib/avo/resources/items/row.rb +54 -0
  93. data/lib/avo/resources/resource_manager.rb +4 -7
  94. data/lib/avo/services/debug_service.rb +6 -6
  95. data/lib/avo/services/telemetry_service.rb +3 -3
  96. data/lib/avo/version.rb +1 -1
  97. data/lib/avo.rb +107 -25
  98. data/lib/generators/avo/action_generator.rb +8 -8
  99. data/lib/generators/avo/card_generator.rb +27 -0
  100. data/lib/generators/avo/filter_generator.rb +8 -8
  101. data/lib/generators/avo/templates/action.tt +3 -3
  102. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  103. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  104. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  105. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  106. data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
  107. data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
  108. data/lib/generators/avo/templates/dashboards/dashboard.tt +1 -1
  109. data/lib/generators/avo/templates/scope.tt +1 -1
  110. data/lib/tasks/avo_tasks.rake +1 -28
  111. data/public/avo-assets/avo.base.css +26 -31
  112. data/public/avo-assets/avo.base.js +281 -280
  113. data/public/avo-assets/avo.base.js.map +3 -3
  114. metadata +21 -8
  115. data/lib/avo/app.rb +0 -170
  116. data/lib/generators/avo/card/chartkick_generator.rb +0 -18
  117. data/lib/generators/avo/card/metric_generator.rb +0 -18
  118. data/lib/generators/avo/card/partial_generator.rb +0 -19
  119. data/lib/generators/avo/templates/standalone_action.tt +0 -15
@@ -5,13 +5,15 @@ def pagy_locale_path(file_name)
5
5
  Avo::Engine.root.join("lib", "generators", "avo", "templates", "locales", "pagy", file_name)
6
6
  end
7
7
 
8
- Pagy::I18n.load(
9
- { locale: 'en' },
10
- { locale: 'fr' },
11
- { locale: 'nb' },
12
- { locale: 'pt-BR' },
13
- { locale: 'pt' },
14
- { locale: 'tr' },
15
- { locale: 'nn', filepath: pagy_locale_path("nn.yml") },
16
- { locale: 'ro', filepath: pagy_locale_path("ro.yml") },
17
- )
8
+ extra_locales = [
9
+ {locale: "en"},
10
+ {locale: "fr"},
11
+ {locale: "nb"},
12
+ {locale: "pt-BR"},
13
+ {locale: "pt"},
14
+ {locale: "tr"},
15
+ {locale: "nn", filepath: pagy_locale_path("nn.yml")},
16
+ {locale: "ro", filepath: pagy_locale_path("ro.yml")}
17
+ ]
18
+
19
+ Pagy::I18n.send(:build, *extra_locales)
data/config/routes.rb CHANGED
@@ -4,9 +4,9 @@ Avo::Engine.routes.draw do
4
4
  get "resources", to: redirect(Avo.configuration.root_path)
5
5
  get "dashboards", to: redirect(Avo.configuration.root_path)
6
6
 
7
- mount AvoFilters::Engine, at: "/avo_filters" if defined?(AvoFilters)
8
- mount AvoDashboards::Engine, at: "/dashboards" if defined?(AvoDashboards::Engine)
9
- mount AvoPro::Engine, at: "/avo_pro" if defined?(AvoPro)
7
+ mount Avo::DynamicFilters::Engine, at: "/avo-dynamic_filters" if defined?(Avo::DynamicFilters::Engine)
8
+ mount Avo::Dashboards::Engine, at: "/dashboards" if defined?(Avo::Dashboards::Engine)
9
+ mount Avo::Pro::Engine, at: "/avo/avo-pro" if defined?(Avo::Pro::Engine)
10
10
 
11
11
  post "/rails/active_storage/direct_uploads", to: "/active_storage/direct_uploads#create"
12
12
 
data/db/factories.rb CHANGED
@@ -110,7 +110,8 @@ FactoryBot.define do
110
110
  factory :city do
111
111
  name { Faker::Address.city }
112
112
  population { rand(10000..999000) }
113
- coordinates { [Faker::Address.latitude, Faker::Address.longitude] }
113
+ latitude { Faker::Address.latitude }
114
+ longitude { Faker::Address.longitude }
114
115
  is_capital { [true, false].sample }
115
116
  features { Faker::Address.community }
116
117
  metadata { Faker::Address.community }
@@ -24,7 +24,9 @@ module Avo
24
24
  delegate :view, to: :class
25
25
  # TODO: find a differnet way to delegate this to the uninitialized Current variable
26
26
  delegate :context, to: Avo::Current
27
- delegate :current_user, to: Avo::Current
27
+ def curent_user
28
+ Avo::Current.user
29
+ end
28
30
  delegate :params, to: Avo::Current
29
31
  delegate :view_context, to: Avo::Current
30
32
  delegate :avo, to: :view_context
@@ -128,7 +130,7 @@ module Avo
128
130
  resource: resource
129
131
  }
130
132
 
131
- args[:records] = records unless standalone
133
+ args[:records] = records
132
134
 
133
135
  handle(**args)
134
136
 
@@ -12,7 +12,9 @@ module Avo
12
12
 
13
13
  # Avo::Current methods
14
14
  delegate :context, to: Avo::Current
15
- delegate :current_user, to: Avo::Current
15
+ def curent_user
16
+ Avo::Current.user
17
+ end
16
18
  delegate :params, to: Avo::Current
17
19
  delegate :request, to: Avo::Current
18
20
  delegate :view_context, to: Avo::Current
@@ -84,6 +86,8 @@ module Avo
84
86
  end
85
87
 
86
88
  # This resolves the scope when doing "where" queries (not find queries)
89
+ #
90
+ # It's used to apply the authorization feature.
87
91
  def query_scope
88
92
  authorization.apply_policy Avo::ExecutionContext.new(
89
93
  target: index_query,
@@ -92,12 +96,14 @@ module Avo
92
96
  end
93
97
 
94
98
  # This resolves the scope when finding records (not "where" queries)
99
+ #
100
+ # It's used to apply the authorization feature.
95
101
  def find_scope
96
102
  authorization.apply_policy model_class
97
103
  end
98
104
 
99
105
  def authorization
100
- Avo::Services::AuthorizationService.new Avo::Current.current_user, model_class, policy_class: authorization_policy
106
+ Avo::Services::AuthorizationService.new Avo::Current.user, model_class, policy_class: authorization_policy
101
107
  end
102
108
 
103
109
  def get_record_associations(record)
@@ -127,8 +133,31 @@ module Avo
127
133
  end
128
134
  end
129
135
 
136
+ # Returns the model class being used for this resource.
137
+ #
138
+ # The Resource instance has a model_class method too so it can support the STI use cases
139
+ # where we figure out the model class from the record
140
+ def model_class(record_class: nil)
141
+ # get the model class off of the static property
142
+ return @model_class if @model_class.present?
143
+
144
+ # get the model class off of the record for STI models
145
+ return record_class if record_class.present?
146
+
147
+ # generate a model class
148
+ class_name.safe_constantize
149
+ end
150
+
151
+ # This is used as the model class ID
152
+ # We use this instead of the route_key to maintain compatibility with uncountable models
153
+ # With uncountable models route key appends an _index suffix (Fish->fish_index)
154
+ # Example: User->users, MediaItem->media_items, Fish->fish
155
+ def model_key
156
+ model_class.model_name.plural
157
+ end
158
+
130
159
  def class_name
131
- name.demodulize
160
+ to_s.demodulize
132
161
  end
133
162
 
134
163
  def route_key
@@ -138,11 +167,81 @@ module Avo
138
167
  def singular_route_key
139
168
  route_key.singularize
140
169
  end
170
+
171
+ def translation_key
172
+ @translation_key || "avo.resource_translations.#{class_name.underscore}"
173
+ end
174
+
175
+ def name
176
+ default = class_name.underscore.humanize
177
+
178
+ if translation_key
179
+ t(translation_key, count: 1, default: default).capitalize
180
+ else
181
+ default
182
+ end
183
+ end
184
+ alias_method :singular_name, :name
185
+
186
+ def plural_name
187
+ default = name.pluralize
188
+
189
+ if translation_key
190
+ t(translation_key, count: 2, default: default).capitalize
191
+ else
192
+ default
193
+ end
194
+ end
195
+
196
+ def underscore_name
197
+ return @name if @name.present?
198
+
199
+ name.demodulize.underscore
200
+ end
201
+
202
+ def navigation_label
203
+ plural_name.humanize
204
+ end
205
+
206
+ def find_record(id, query: nil, params: nil)
207
+ Avo::ExecutionContext.new(
208
+ target: find_record_method,
209
+ query: query || find_scope, # If no record is given we'll use the default
210
+ id: id,
211
+ params: params
212
+ ).handle
213
+ end
214
+
215
+ def search_query
216
+ search.dig(:query)
217
+ end
218
+
219
+ def fetch_search(key, record: nil)
220
+ # self.class.fetch_search
221
+ Avo::ExecutionContext.new(target: search[key], resource: self, record: record).handle
222
+ end
141
223
  end
142
224
 
143
225
  delegate :context, to: ::Avo::Current
226
+ delegate :name, to: :class
227
+ delegate :singular_name, to: :class
228
+ delegate :plural_name, to: :class
229
+ delegate :underscore_name, to: :class
230
+ delegate :underscore_name, to: :class
231
+ delegate :find_record, to: :class
232
+ delegate :model_key, to: :class
233
+
234
+ def initialize(record: nil, view: nil, user: nil, params: nil)
235
+ @view = view if view.present?
236
+ @user = user if user.present?
237
+ @params = params if params.present?
238
+
239
+ if record.present?
240
+ @record = record
241
+
242
+ hydrate_model_with_default_values if @view == :new
243
+ end
144
244
 
145
- def initialize
146
245
  detect_fields
147
246
 
148
247
  unless self.class.model_class.present?
@@ -194,7 +293,7 @@ module Avo
194
293
 
195
294
  # def get_action_arguments / def get_filter_arguments / def get_scope_arguments
196
295
  define_method "get_#{entity}_arguments" do |entity_class|
197
- send("get_#{plural_entity}").find { |entity| entity[:class] == entity_class.constantize }[:arguments]
296
+ send("get_#{plural_entity}").find { |entity| entity[:class].to_s == entity_class.to_s }[:arguments]
198
297
  end
199
298
  end
200
299
 
@@ -225,15 +324,14 @@ module Avo
225
324
  end
226
325
  end
227
326
 
327
+ # Returns the model class being used for this resource.
328
+ #
329
+ # We use the class method as a fallback but we pass it the record too so it can support the STI use cases
330
+ # where we figure out the model class from that record.
228
331
  def model_class
229
- # get the model class off of the static property
230
- return self.class.model_class if self.class.model_class.present?
231
-
232
- # get the model class off of the record
233
- return @record.base_class if @record.present?
332
+ record_class = @record&.class
234
333
 
235
- # generate a model class
236
- class_name.safe_constantize
334
+ self.class.model_class record_class: record_class
237
335
  end
238
336
 
239
337
  def record_title
@@ -251,46 +349,6 @@ module Avo
251
349
  end
252
350
  end
253
351
 
254
- def translation_key
255
- self.class.translation_key || "avo.resource_translations.#{class_name.underscore}"
256
- end
257
-
258
- def name
259
- return @name if @name.present?
260
-
261
- default = class_name.underscore.humanize
262
-
263
- if translation_key
264
- t(translation_key, count: 1, default: default).capitalize
265
- else
266
- default
267
- end
268
- end
269
-
270
- def singular_name
271
- name
272
- end
273
-
274
- def plural_name
275
- default = name.pluralize
276
-
277
- if translation_key
278
- t(translation_key, count: 2, default: default).capitalize
279
- else
280
- default
281
- end
282
- end
283
-
284
- def underscore_name
285
- return @name if @name.present?
286
-
287
- self.class.name.demodulize.underscore
288
- end
289
-
290
- def navigation_label
291
- plural_name.humanize
292
- end
293
-
294
352
  def available_view_types
295
353
  if self.class.view_types.present?
296
354
  return Array(
@@ -310,15 +368,15 @@ module Avo
310
368
  view_types
311
369
  end
312
370
 
313
- def attached_file_fields
371
+ def attachment_fields
314
372
  get_field_definitions.select do |field|
315
373
  [Avo::Fields::FileField, Avo::Fields::FilesField].include? field.class
316
374
  end
317
375
  end
318
376
 
319
- def fill_record(record, params, extra_params: [])
320
- # Map the received params to their actual fields
321
- fields_by_database_id = get_field_definitions
377
+ # Map the received params to their actual fields
378
+ def fields_by_database_id
379
+ get_field_definitions
322
380
  .reject do |field|
323
381
  field.computed
324
382
  end
@@ -326,7 +384,9 @@ module Avo
326
384
  [field.database_id.to_s, field]
327
385
  end
328
386
  .to_h
387
+ end
329
388
 
389
+ def fill_record(record, params, extra_params: [])
330
390
  # Write the field values
331
391
  params.each do |key, value|
332
392
  field = fields_by_database_id[key]
@@ -346,7 +406,7 @@ module Avo
346
406
  end
347
407
 
348
408
  def authorization(user: nil)
349
- current_user = user || Avo::Current.current_user
409
+ current_user = user || Avo::Current.user
350
410
  Avo::Services::AuthorizationService.new(current_user, record || model_class, policy_class: authorization_policy)
351
411
  end
352
412
 
@@ -383,20 +443,18 @@ module Avo
383
443
  !field.computed
384
444
  end
385
445
  .map do |field|
386
- id = field.id
387
446
  value = field.value
388
447
 
389
448
  if field.type == "belongs_to"
390
- id = field.foreign_key.to_sym
391
449
 
392
450
  reflection = @record._reflections[@params[:via_relation]]
393
451
 
394
452
  if field.polymorphic_as.present? && field.types.map(&:to_s).include?(@params[:via_relation_class])
395
453
  # set the value to the actual record
396
- via_resource = Avo::App.resources.get_resource_by_model_class(@params[:via_relation_class])
454
+ via_resource = Avo.resource_manager.get_resource_by_model_class(@params[:via_relation_class])
397
455
  value = via_resource.find_record(@params[:via_record_id])
398
456
  elsif reflection.present? && reflection.foreign_key.present? && field.id.to_s == @params[:via_relation].to_s
399
- resource = Avo::App.resources.get_resource_by_model_class params[:via_relation_class]
457
+ resource = Avo.resource_manager.get_resource_by_model_class params[:via_relation_class]
400
458
  record = resource.find_record @params[:via_record_id], params: params
401
459
  id_param = reflection.options[:primary_key] || :id
402
460
 
@@ -404,28 +462,18 @@ module Avo
404
462
  end
405
463
  end
406
464
 
407
- [id, value]
465
+ [field, value]
408
466
  end
409
467
  .to_h
410
- .select do |id, value|
468
+ .select do |_, value|
411
469
  value.present?
412
470
  end
413
471
 
414
- default_values.each do |id, value|
415
- if @record.send(id).nil?
416
- @record.send("#{id}=", value)
417
- end
472
+ default_values.each do |field, value|
473
+ field.assign_value record: @record, value: value
418
474
  end
419
475
  end
420
476
 
421
- # This is used as the model class ID
422
- # We use this instead of the route_key to maintain compatibility with uncountable models
423
- # With uncountable models route key appends an _index suffix (Fish->fish_index)
424
- # Example: User->users, MediaItem->media_items, Fish->fish
425
- def model_key
426
- model_class.model_name.plural
427
- end
428
-
429
477
  def model_name
430
478
  model_class.model_name
431
479
  end
@@ -474,15 +522,6 @@ module Avo
474
522
  record.present? && record_id.present?
475
523
  end
476
524
 
477
- def find_record(id, query: nil, params: nil)
478
- Avo::ExecutionContext.new(
479
- target: self.class.find_record_method,
480
- query: query || self.class.find_scope,
481
- id: id,
482
- params: params
483
- ).handle
484
- end
485
-
486
525
  def id_attribute
487
526
  :id
488
527
  end
@@ -499,14 +538,6 @@ module Avo
499
538
  }
500
539
  end
501
540
 
502
- def search_query
503
- self.class.search.dig(:query)
504
- end
505
-
506
- def fetch_search(key)
507
- Avo::ExecutionContext.new(target: self.class.search[key], resource: self, record: record).handle
508
- end
509
-
510
541
  private
511
542
 
512
543
  def entity_loader(entity)
@@ -33,6 +33,10 @@ module Avo
33
33
  def is_sidebar?
34
34
  self.class.ancestors.include?(Avo::Resources::Items::Sidebar)
35
35
  end
36
+
37
+ def is_row?
38
+ self.class.respond_to?(:item_type) && self.class.item_type == :row
39
+ end
36
40
  end
37
41
  end
38
42
  end
@@ -18,6 +18,10 @@ module Avo
18
18
  deprecated_dsl_api __method__, "fields"
19
19
  end
20
20
 
21
+ def row(**args, &block)
22
+ deprecated_dsl_api __method__, "fields"
23
+ end
24
+
21
25
  def tabs(**args, &block)
22
26
  deprecated_dsl_api __method__, "fields"
23
27
  end
@@ -42,6 +46,7 @@ module Avo
42
46
 
43
47
  delegate :field, to: :items_holder
44
48
  delegate :panel, to: :items_holder
49
+ delegate :row, to: :items_holder
45
50
  delegate :tabs, to: :items_holder
46
51
  delegate :tool, to: :items_holder
47
52
  delegate :heading, to: :items_holder
@@ -96,6 +101,10 @@ module Avo
96
101
  if item.is_field?
97
102
  fields << item
98
103
  end
104
+
105
+ if item.is_row?
106
+ fields << extract_fields_from_items(tab)
107
+ end
99
108
  end
100
109
 
101
110
  fields.flatten
@@ -213,8 +222,10 @@ module Avo
213
222
  panelfull_items.grep(Avo::Resources::Items::TabGroup).each do |tab_group|
214
223
  tab_group.items.grep(Avo::Resources::Items::Tab).each do |tab|
215
224
  tab.items.grep(Avo::Resources::Items::Panel).each do |panel|
216
- panel.items.grep(Avo::Fields::BelongsToField).each do |field|
217
- field.target = :_top
225
+ set_target_to_top panel.items.grep(Avo::Fields::BelongsToField)
226
+
227
+ panel.items.grep(Avo::Resources::Items::Row).each do |row|
228
+ set_target_to_top row.items.grep(Avo::Fields::BelongsToField)
218
229
  end
219
230
  end
220
231
  end
@@ -250,9 +261,6 @@ module Avo
250
261
 
251
262
  item
252
263
  end
253
- .select do |item|
254
- item.visible_in_view?(view: view)
255
- end
256
264
  .select do |item|
257
265
  item.visible?
258
266
  end
@@ -264,7 +272,8 @@ module Avo
264
272
  end
265
273
  end
266
274
  .select do |item|
267
- if !item.is_heading? && view.in?([:edit, :update, :new, :create])
275
+ # On location field we can have field coordinates and setters with different names like latitude and longitude
276
+ if !item.is_a?(Avo::Fields::LocationField) && !item.is_heading? && view.in?([:edit, :update, :new, :create])
268
277
  if item.respond_to?(:id)
269
278
  item.resource.record.respond_to?("#{item.id}=")
270
279
  else
@@ -290,25 +299,21 @@ module Avo
290
299
  visible_items.blank?
291
300
  end
292
301
 
293
- def hydrate(**args)
294
- super(**args)
302
+ private
295
303
 
296
- items_holder.items.each do |item|
297
- item.hydrate(**args)
304
+ def set_target_to_top(fields)
305
+ fields.each do |field|
306
+ field.target = :_top
298
307
  end
299
-
300
- self
301
308
  end
302
309
 
303
- private
304
-
305
310
  def extract_fields_from_items(thing)
306
311
  fields = []
307
312
 
308
313
  thing.items.each do |item|
309
314
  if item.is_field?
310
315
  fields << item
311
- elsif item.is_panel?
316
+ elsif item.is_panel? || item.is_row?
312
317
  fields << extract_fields_from_items(item)
313
318
  end
314
319
  end
@@ -4,8 +4,6 @@ module Avo
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  class_methods do
7
- attr_reader :model_class
8
-
9
7
  # Cast the model class to a constantized version and memoize it like that
10
8
  def model_class=(value)
11
9
  @model_class = case value
data/lib/avo/current.rb CHANGED
@@ -1,12 +1,39 @@
1
1
  class Avo::Current < ActiveSupport::CurrentAttributes
2
+ # if Rails.env.development?
3
+ # singleton_class.attr_accessor :previous_attributes
4
+ # before_reset {
5
+ # puts ["before_reset->", self.previous_attributes].inspect
6
+ # if attributes.present?
7
+ # puts ["has attributes->"].inspect
8
+ # self.previous_attributes = attributes
9
+ # end
10
+ # puts ["before_reset->", self.previous_attributes].inspect
11
+ # }
12
+
13
+ # attr_accessor :previous_attributes
14
+
15
+ # def previous_attributes=(value)
16
+ # @previous_attributes = value
17
+ # end
18
+ # end
19
+
2
20
  attribute :app
3
21
  attribute :license
4
- attribute :context, :current_user, :view_context
22
+ attribute :context, :user, :view_context
23
+ attribute :error_manager
24
+ attribute :resource_manager
25
+ attribute :tool_manager
26
+ attribute :plugin_manager
5
27
 
6
- delegate :request, to: :view_context
7
28
  delegate :params, to: :request
8
29
 
9
30
  def request
10
31
  view_context.request || ActionDispatch::Request.empty
11
32
  end
33
+
34
+ def current_user
35
+ Rails.logger.warn "DEPRECATION WARNING: Avo::Current.current_user become deprecated and will become obsolete on futhure versions. Please use Avo::Current.user instead."
36
+
37
+ user
38
+ end
12
39
  end
@@ -72,7 +72,7 @@ module Avo
72
72
  end
73
73
 
74
74
  def field_class_from_symbol(symbol)
75
- matched_field = Avo::App.fields.all.find do |field|
75
+ matched_field = Avo.field_manager.all.find do |field|
76
76
  field[:name].to_s == symbol.to_s
77
77
  end
78
78
 
@@ -1,12 +1,23 @@
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
+
3
14
  def self.routes
4
15
  Avo::Engine.routes.draw do
5
16
  scope "resources", as: "resources" do
6
17
  # Check if the user chose to manually register the resource files.
7
18
  # If so, eager_load the resources dir.
8
19
  if Avo.configuration.resources.nil?
9
- Avo::App.eager_load(:resources) unless Rails.application.config.eager_load
20
+ Avo::DynamicRouter.eager_load(:resources) unless Rails.application.config.eager_load
10
21
  end
11
22
 
12
23
  Avo::Resources::ResourceManager.fetch_resources
data/lib/avo/engine.rb CHANGED
@@ -3,6 +3,8 @@ Gem.loaded_specs["avo"].dependencies.each do |d|
3
3
  case d.name
4
4
  when "activerecord"
5
5
  require "active_record/railtie"
6
+ when "activesupport"
7
+ require "active_support/railtie"
6
8
  when "actionview"
7
9
  require "action_view/railtie"
8
10
  when "activestorage"
@@ -23,7 +25,7 @@ module Avo
23
25
  ::Avo.asset_manager.reset
24
26
 
25
27
  # Boot Avo
26
- ::Avo::App.boot
28
+ ::Avo.boot
27
29
 
28
30
  # After deploy we want to make sure the license response is being cleared.
29
31
  # We need a fresh license response.
@@ -40,7 +42,7 @@ module Avo
40
42
  # Ensure we reboot the app when something changes
41
43
  config.to_prepare do
42
44
  # Boot Avo
43
- ::Avo::App.boot
45
+ ::Avo.boot
44
46
  end
45
47
 
46
48
  initializer "avo.autoload" do |app|
@@ -55,10 +57,6 @@ module Avo
55
57
  end
56
58
  end
57
59
 
58
- initializer "avo.init_fields" do |app|
59
- ::Avo::App.init_fields
60
- end
61
-
62
60
  initializer "avo.reloader" do |app|
63
61
  Avo::Reloader.new.tap do |reloader|
64
62
  reloader.execute
@@ -94,7 +92,6 @@ module Avo
94
92
 
95
93
  initializer "avo.locales" do |app|
96
94
  I18n.load_path += Dir[Avo::Engine.root.join("lib", "generators", "avo", "templates", "locales", "*.{rb,yml}")]
97
- I18n.load_path += Dir[Rails.root.join("config", "locales", "*.{rb,yml}")]
98
95
  end
99
96
  end
100
97
  end
@@ -20,7 +20,7 @@ module Avo
20
20
 
21
21
  # Set defaults on not initialized accessors
22
22
  @context ||= Avo::Current.context
23
- @current_user ||= Avo::Current.current_user
23
+ @current_user ||= Avo::Current.user
24
24
  @params ||= Avo::Current.params
25
25
  @request ||= Avo::Current.request
26
26
  @view_context ||= Avo::Current.view_context