avo 3.0.0.pre12 → 3.0.0.pre14
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of avo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -1
- data/app/assets/stylesheets/avo.base.css +1 -1
- data/app/components/avo/actions_component.html.erb +1 -1
- data/app/components/avo/actions_component.rb +40 -16
- data/app/components/avo/alert_component.html.erb +1 -1
- data/app/components/avo/base_component.rb +7 -7
- data/app/components/avo/field_wrapper_component.html.erb +2 -2
- data/app/components/avo/field_wrapper_component.rb +1 -1
- data/app/components/avo/fields/area_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +5 -5
- data/app/components/avo/fields/belongs_to_field/edit_component.rb +4 -4
- data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/code_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/common/heading_component.html.erb +1 -1
- data/app/components/avo/fields/country_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/file_field/index_component.rb +2 -2
- data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -0
- data/app/components/avo/fields/index_component.rb +1 -0
- data/app/components/avo/fields/location_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/markdown_field/edit_component.html.erb +4 -3
- data/app/components/avo/fields/markdown_field/show_component.html.erb +3 -3
- data/app/components/avo/fields/number_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/password_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/text_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/textarea_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/trix_field/edit_component.html.erb +2 -1
- data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
- data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
- data/app/components/avo/index/grid_item_component.html.erb +9 -35
- data/app/components/avo/index/grid_item_component.rb +36 -10
- data/app/components/avo/index/resource_controls_component.rb +6 -6
- data/app/components/avo/item_switcher_component.html.erb +9 -4
- data/app/components/avo/item_switcher_component.rb +2 -1
- data/app/components/avo/panel_component.html.erb +1 -1
- data/app/components/avo/profile_item_component.html.erb +17 -2
- data/app/components/avo/profile_item_component.rb +13 -1
- data/app/components/avo/resource_component.rb +6 -3
- data/app/components/avo/resource_sidebar_component.rb +1 -1
- data/app/components/avo/row_component.html.erb +3 -0
- data/app/components/avo/row_component.rb +12 -0
- data/app/components/avo/sidebar/link_component.html.erb +2 -0
- data/app/components/avo/sidebar/link_component.rb +5 -3
- data/app/components/avo/sidebar_component.html.erb +3 -3
- data/app/components/avo/sidebar_component.rb +4 -4
- data/app/components/avo/sidebar_profile_component.html.erb +27 -27
- data/app/components/avo/views/resource_edit_component.rb +1 -1
- data/app/components/avo/views/resource_index_component.html.erb +1 -1
- data/app/components/avo/views/resource_index_component.rb +8 -8
- data/app/controllers/avo/actions_controller.rb +22 -8
- data/app/controllers/avo/application_controller.rb +71 -66
- data/app/controllers/avo/associations_controller.rb +4 -6
- data/app/controllers/avo/attachments_controller.rb +1 -1
- data/app/controllers/avo/base_controller.rb +36 -17
- data/app/controllers/avo/home_controller.rb +1 -1
- data/app/controllers/avo/search_controller.rb +18 -20
- data/app/controllers/concerns/avo/initializes_avo.rb +2 -5
- data/app/javascript/js/controllers/fields/{simple_mde_controller.js → easy_mde_controller.js} +4 -3
- data/app/javascript/js/controllers/search_controller.js +3 -1
- data/app/javascript/js/controllers.js +2 -2
- data/app/views/avo/actions/show.html.erb +2 -1
- data/app/views/avo/associations/new.html.erb +1 -1
- data/app/views/avo/debug/status.html.erb +1 -1
- data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
- data/app/views/avo/partials/_footer.html.erb +1 -1
- data/app/views/avo/partials/_javascript.html.erb +1 -1
- data/app/views/avo/partials/_navbar.html.erb +1 -1
- data/app/views/avo/partials/_profile_menu_extra.html.erb +2 -0
- data/app/views/layouts/avo/application.html.erb +2 -2
- data/avo.gemspec +1 -0
- data/config/initializers/pagy.rb +12 -10
- data/config/routes.rb +3 -3
- data/db/factories.rb +2 -1
- data/lib/avo/base_action.rb +12 -2
- data/lib/avo/base_resource.rb +178 -178
- data/lib/avo/concerns/filters_session_handler.rb +0 -1
- data/lib/avo/concerns/has_item_type.rb +4 -0
- data/lib/avo/concerns/has_items.rb +28 -23
- data/lib/avo/concerns/model_class_constantized.rb +0 -2
- data/lib/avo/configuration.rb +6 -2
- data/lib/avo/current.rb +22 -1
- data/lib/avo/dsl/field_parser.rb +1 -1
- data/lib/avo/dynamic_router.rb +12 -1
- data/lib/avo/engine.rb +8 -6
- data/lib/avo/fields/base_field.rb +25 -7
- data/lib/avo/fields/belongs_to_field.rb +20 -13
- data/lib/avo/fields/concerns/is_searchable.rb +1 -1
- data/lib/avo/fields/concerns/use_resource.rb +1 -1
- data/lib/avo/fields/field_manager.rb +13 -3
- data/lib/avo/fields/has_base_field.rb +5 -5
- data/lib/avo/fields/has_one_field.rb +1 -1
- data/lib/avo/fields/location_field.rb +18 -1
- data/lib/avo/licensing/h_q.rb +11 -6
- data/lib/avo/licensing/license.rb +1 -1
- data/lib/avo/licensing/license_manager.rb +1 -1
- data/lib/avo/licensing/{null_license.rb → nil_license.rb} +1 -1
- data/lib/avo/loaders/fields_loader.rb +7 -1
- data/lib/avo/plugin_manager.rb +2 -4
- data/lib/avo/reloader.rb +1 -1
- data/lib/avo/resources/controls/actions_list.rb +2 -1
- data/lib/avo/resources/items/holder.rb +5 -1
- data/lib/avo/resources/items/item_group.rb +1 -0
- data/lib/avo/resources/items/row.rb +54 -0
- data/lib/avo/resources/resource_manager.rb +4 -7
- data/lib/avo/services/debug_service.rb +6 -6
- data/lib/avo/services/telemetry_service.rb +3 -3
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +107 -25
- data/lib/generators/avo/action_generator.rb +8 -8
- data/lib/generators/avo/card_generator.rb +27 -0
- data/lib/generators/avo/eject_generator.rb +1 -0
- data/lib/generators/avo/filter_generator.rb +8 -8
- data/lib/generators/avo/install_generator.rb +0 -1
- data/lib/generators/avo/resource_generator.rb +4 -1
- data/lib/generators/avo/templates/action.tt +3 -3
- data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
- data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
- data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
- data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
- data/lib/generators/avo/templates/dashboards/dashboard.tt +1 -1
- data/lib/generators/avo/templates/resource/resource.tt +3 -4
- data/lib/generators/avo/templates/scope.tt +1 -1
- data/lib/tasks/avo_tasks.rake +1 -1
- data/public/avo-assets/avo.base.css +295 -165
- data/public/avo-assets/avo.base.js +307 -278
- data/public/avo-assets/avo.base.js.map +3 -3
- metadata +23 -10
- data/lib/avo/app.rb +0 -170
- data/lib/avo/grid_collector.rb +0 -40
- data/lib/generators/avo/card/chartkick_generator.rb +0 -18
- data/lib/generators/avo/card/metric_generator.rb +0 -18
- data/lib/generators/avo/card/partial_generator.rb +0 -19
- data/lib/generators/avo/templates/standalone_action.tt +0 -15
@@ -60,8 +60,8 @@
|
|
60
60
|
<%= render partial: "avo/partials/scripts" %>
|
61
61
|
<!-- Avo version: <%= Avo::VERSION %> -->
|
62
62
|
<!-- Environment: <%= Rails.env %> -->
|
63
|
-
<!-- License ID: <%= Avo
|
64
|
-
<!-- License valid?: <%= Avo
|
63
|
+
<!-- License ID: <%= Avo.license.id %> -->
|
64
|
+
<!-- License valid?: <%= Avo.license.valid ? "valid" : "invalid" %> -->
|
65
65
|
</body>
|
66
66
|
</html>
|
67
67
|
<!-- ✨ Built with Avo • https://www.avohq.io/ -->
|
data/avo.gemspec
CHANGED
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.files = Dir["{bin,app,config,db,lib,public}/**/*", "MIT-LICENSE", "Rakefile", "README.md", "avo.gemspec", "Gemfile", "Gemfile.lock"]
|
34
34
|
|
35
35
|
spec.add_dependency "activerecord", ">= 6.1"
|
36
|
+
spec.add_dependency "activesupport", ">= 6.1"
|
36
37
|
spec.add_dependency "actionview", ">= 6.1"
|
37
38
|
spec.add_dependency "pagy"
|
38
39
|
spec.add_dependency "zeitwerk", ">= 2.6.2"
|
data/config/initializers/pagy.rb
CHANGED
@@ -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
|
-
|
9
|
-
{
|
10
|
-
{
|
11
|
-
{
|
12
|
-
{
|
13
|
-
{
|
14
|
-
{
|
15
|
-
{
|
16
|
-
{
|
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
|
8
|
-
mount
|
9
|
-
mount
|
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
|
-
|
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 }
|
data/lib/avo/base_action.rb
CHANGED
@@ -86,7 +86,14 @@ module Avo
|
|
86
86
|
|
87
87
|
def get_attributes_for_action
|
88
88
|
get_fields.map do |field|
|
89
|
-
|
89
|
+
value = field.value || Avo::ExecutionContext.new(
|
90
|
+
target: field.default,
|
91
|
+
record: self.class.record,
|
92
|
+
resource: self.class.resource,
|
93
|
+
view: view
|
94
|
+
).handle
|
95
|
+
|
96
|
+
[field.id, value]
|
90
97
|
end.to_h
|
91
98
|
end
|
92
99
|
|
@@ -94,12 +101,15 @@ module Avo
|
|
94
101
|
records, fields, current_user, resource = args.values_at(:records, :fields, :current_user, :resource)
|
95
102
|
# Fetching the field definitions and not the actual fields (get_fields) because they will break if the user uses a `visible` block and adds a condition using the `params` variable. The params are different in the show method and the handle method.
|
96
103
|
action_fields = get_field_definitions.map { |field| [field.id, field] }.to_h
|
104
|
+
puts ["action_fields->", action_fields].inspect
|
97
105
|
|
98
106
|
# For some fields, like belongs_to, the id and database_id differ (user vs user_id).
|
99
107
|
# That's why we need to fetch the database_id for when we process the action.
|
100
108
|
action_fields_by_database_id = action_fields.map do |id, value|
|
101
109
|
[value.database_id.to_sym, value]
|
102
110
|
end.to_h
|
111
|
+
puts ["action_fields_by_database_id->", action_fields_by_database_id].inspect
|
112
|
+
abort 1.inspect
|
103
113
|
|
104
114
|
if fields.present?
|
105
115
|
processed_fields = fields.to_unsafe_h.map do |name, value|
|
@@ -121,7 +131,7 @@ module Avo
|
|
121
131
|
resource: resource
|
122
132
|
}
|
123
133
|
|
124
|
-
args[:records] = records
|
134
|
+
args[:records] = records
|
125
135
|
|
126
136
|
handle(**args)
|
127
137
|
|
data/lib/avo/base_resource.rb
CHANGED
@@ -38,19 +38,17 @@ module Avo
|
|
38
38
|
attr_accessor :record
|
39
39
|
|
40
40
|
class_attribute :id, default: :id
|
41
|
-
class_attribute :title
|
42
|
-
class_attribute :
|
43
|
-
class_attribute :search_query_help, default: ""
|
44
|
-
class_attribute :search_result_path
|
41
|
+
class_attribute :title
|
42
|
+
class_attribute :search, default: {}
|
45
43
|
class_attribute :includes, default: []
|
46
44
|
class_attribute :authorization_policy
|
47
45
|
class_attribute :translation_key
|
48
46
|
class_attribute :default_view_type, default: :table
|
49
47
|
class_attribute :devise_password_optional, default: false
|
50
|
-
class_attribute :actions_loader
|
51
48
|
class_attribute :scopes_loader
|
52
49
|
class_attribute :filters_loader
|
53
|
-
class_attribute :
|
50
|
+
class_attribute :view_types
|
51
|
+
class_attribute :grid_view
|
54
52
|
class_attribute :visible_on_sidebar, default: true
|
55
53
|
class_attribute :index_query, default: -> {
|
56
54
|
query
|
@@ -58,7 +56,6 @@ module Avo
|
|
58
56
|
class_attribute :find_record_method, default: -> {
|
59
57
|
query.find id
|
60
58
|
}
|
61
|
-
class_attribute :hide_from_global_search, default: false
|
62
59
|
class_attribute :after_create_path, default: :show
|
63
60
|
class_attribute :after_update_path, default: :show
|
64
61
|
class_attribute :record_selector, default: true
|
@@ -74,42 +71,21 @@ module Avo
|
|
74
71
|
delegate :t, to: ::I18n
|
75
72
|
delegate :context, to: ::Avo::Current
|
76
73
|
|
77
|
-
def grid(&block)
|
78
|
-
grid_collector = GridCollector.new
|
79
|
-
grid_collector.instance_eval(&block)
|
80
|
-
|
81
|
-
self.grid_loader = grid_collector
|
82
|
-
end
|
83
|
-
|
84
74
|
def action(action_class, arguments: {})
|
85
|
-
|
86
|
-
|
87
|
-
action = {class: action_class, arguments: arguments}
|
88
|
-
self.actions_loader.use action
|
75
|
+
deprecated_dsl_api __method__, "actions"
|
89
76
|
end
|
90
77
|
|
91
78
|
def filter(filter_class, arguments: {})
|
92
|
-
|
93
|
-
|
94
|
-
filter = { class: filter_class , arguments: arguments }
|
95
|
-
self.filters_loader.use filter
|
96
|
-
end
|
97
|
-
|
98
|
-
# This is the search_query scope
|
99
|
-
# This should be removed and passed to the search block
|
100
|
-
def scope
|
101
|
-
query_scope
|
79
|
+
deprecated_dsl_api __method__, "filters"
|
102
80
|
end
|
103
81
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
args.each do |scope_class|
|
108
|
-
self.scopes_loader.use scope_class
|
109
|
-
end
|
82
|
+
def scope(scope_class)
|
83
|
+
deprecated_dsl_api __method__, "scopes"
|
110
84
|
end
|
111
85
|
|
112
86
|
# This resolves the scope when doing "where" queries (not find queries)
|
87
|
+
#
|
88
|
+
# It's used to apply the authorization feature.
|
113
89
|
def query_scope
|
114
90
|
authorization.apply_policy Avo::ExecutionContext.new(
|
115
91
|
target: index_query,
|
@@ -118,6 +94,8 @@ module Avo
|
|
118
94
|
end
|
119
95
|
|
120
96
|
# This resolves the scope when finding records (not "where" queries)
|
97
|
+
#
|
98
|
+
# It's used to apply the authorization feature.
|
121
99
|
def find_scope
|
122
100
|
authorization.apply_policy model_class
|
123
101
|
end
|
@@ -153,8 +131,31 @@ module Avo
|
|
153
131
|
end
|
154
132
|
end
|
155
133
|
|
134
|
+
# Returns the model class being used for this resource.
|
135
|
+
#
|
136
|
+
# The Resource instance has a model_class method too so it can support the STI use cases
|
137
|
+
# where we figure out the model class from the record
|
138
|
+
def model_class(record_class: nil)
|
139
|
+
# get the model class off of the static property
|
140
|
+
return @model_class if @model_class.present?
|
141
|
+
|
142
|
+
# get the model class off of the record for STI models
|
143
|
+
return record_class if record_class.present?
|
144
|
+
|
145
|
+
# generate a model class
|
146
|
+
class_name.safe_constantize
|
147
|
+
end
|
148
|
+
|
149
|
+
# This is used as the model class ID
|
150
|
+
# We use this instead of the route_key to maintain compatibility with uncountable models
|
151
|
+
# With uncountable models route key appends an _index suffix (Fish->fish_index)
|
152
|
+
# Example: User->users, MediaItem->media_items, Fish->fish
|
153
|
+
def model_key
|
154
|
+
model_class.model_name.plural
|
155
|
+
end
|
156
|
+
|
156
157
|
def class_name
|
157
|
-
|
158
|
+
to_s.demodulize
|
158
159
|
end
|
159
160
|
|
160
161
|
def route_key
|
@@ -164,11 +165,81 @@ module Avo
|
|
164
165
|
def singular_route_key
|
165
166
|
route_key.singularize
|
166
167
|
end
|
168
|
+
|
169
|
+
def translation_key
|
170
|
+
@translation_key || "avo.resource_translations.#{class_name.underscore}"
|
171
|
+
end
|
172
|
+
|
173
|
+
def name
|
174
|
+
default = class_name.underscore.humanize
|
175
|
+
|
176
|
+
if translation_key
|
177
|
+
t(translation_key, count: 1, default: default).capitalize
|
178
|
+
else
|
179
|
+
default
|
180
|
+
end
|
181
|
+
end
|
182
|
+
alias_method :singular_name, :name
|
183
|
+
|
184
|
+
def plural_name
|
185
|
+
default = name.pluralize
|
186
|
+
|
187
|
+
if translation_key
|
188
|
+
t(translation_key, count: 2, default: default).capitalize
|
189
|
+
else
|
190
|
+
default
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def underscore_name
|
195
|
+
return @name if @name.present?
|
196
|
+
|
197
|
+
name.demodulize.underscore
|
198
|
+
end
|
199
|
+
|
200
|
+
def navigation_label
|
201
|
+
plural_name.humanize
|
202
|
+
end
|
203
|
+
|
204
|
+
def find_record(id, query: nil, params: nil)
|
205
|
+
Avo::ExecutionContext.new(
|
206
|
+
target: find_record_method,
|
207
|
+
query: query || find_scope, # If no record is given we'll use the default
|
208
|
+
id: id,
|
209
|
+
params: params
|
210
|
+
).handle
|
211
|
+
end
|
212
|
+
|
213
|
+
def search_query
|
214
|
+
search.dig(:query)
|
215
|
+
end
|
216
|
+
|
217
|
+
def fetch_search(key, record: nil)
|
218
|
+
# self.class.fetch_search
|
219
|
+
Avo::ExecutionContext.new(target: search[key], resource: self, record: record).handle
|
220
|
+
end
|
167
221
|
end
|
168
222
|
|
169
223
|
delegate :context, to: ::Avo::Current
|
224
|
+
delegate :name, to: :class
|
225
|
+
delegate :singular_name, to: :class
|
226
|
+
delegate :plural_name, to: :class
|
227
|
+
delegate :underscore_name, to: :class
|
228
|
+
delegate :underscore_name, to: :class
|
229
|
+
delegate :find_record, to: :class
|
230
|
+
delegate :model_key, to: :class
|
231
|
+
|
232
|
+
def initialize(record: nil, view: nil, user: nil, params: nil)
|
233
|
+
@view = view if view.present?
|
234
|
+
@user = user if user.present?
|
235
|
+
@params = params if params.present?
|
236
|
+
|
237
|
+
if record.present?
|
238
|
+
@record = record
|
239
|
+
|
240
|
+
hydrate_model_with_default_values if @view == :new
|
241
|
+
end
|
170
242
|
|
171
|
-
def initialize
|
172
243
|
detect_fields
|
173
244
|
|
174
245
|
unless self.class.model_class.present?
|
@@ -195,54 +266,47 @@ module Avo
|
|
195
266
|
# blank fields method
|
196
267
|
end
|
197
268
|
|
198
|
-
|
199
|
-
|
200
|
-
@user = user if user.present?
|
201
|
-
@params = params if params.present?
|
202
|
-
|
203
|
-
if record.present?
|
204
|
-
@record = record
|
269
|
+
[:action, :filter, :scope].each do |entity|
|
270
|
+
plural_entity = entity.to_s.pluralize
|
205
271
|
|
206
|
-
|
272
|
+
# def actions / def filters / def scopes
|
273
|
+
define_method plural_entity do
|
274
|
+
# blank entity method
|
207
275
|
end
|
208
276
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
return if self.class.grid_loader.blank?
|
214
|
-
|
215
|
-
self.class.grid_loader.hydrate(record: @record, view: @view, resource: self)
|
216
|
-
end
|
217
|
-
|
218
|
-
def get_filters
|
219
|
-
return [] if self.class.filters_loader.blank?
|
220
|
-
|
221
|
-
self.class.filters_loader.bag
|
222
|
-
end
|
277
|
+
# def action / def filter / def scope
|
278
|
+
define_method entity do |entity_class, arguments: {}|
|
279
|
+
entity_loader(entity).use({class: entity_class, arguments: arguments})
|
280
|
+
end
|
223
281
|
|
224
|
-
|
225
|
-
|
282
|
+
# def get_actions / def get_filters / def get_scopes
|
283
|
+
define_method "get_#{plural_entity}" do
|
284
|
+
return entity_loader(entity).bag if entity_loader(entity).present?
|
226
285
|
|
227
|
-
|
228
|
-
|
286
|
+
instance_variable_set("@#{plural_entity}_loader", Avo::Loaders::Loader.new)
|
287
|
+
send plural_entity
|
229
288
|
|
230
|
-
|
231
|
-
|
289
|
+
entity_loader(entity).bag
|
290
|
+
end
|
232
291
|
|
233
|
-
|
292
|
+
# def get_action_arguments / def get_filter_arguments / def get_scope_arguments
|
293
|
+
define_method "get_#{entity}_arguments" do |entity_class|
|
294
|
+
send("get_#{plural_entity}").find { |entity| entity[:class].to_s == entity_class.to_s }[:arguments]
|
295
|
+
end
|
234
296
|
end
|
235
297
|
|
236
|
-
def
|
237
|
-
|
298
|
+
def hydrate(record: nil, view: nil, user: nil, params: nil)
|
299
|
+
@view = view if view.present?
|
300
|
+
@user = user if user.present?
|
301
|
+
@params = params if params.present?
|
238
302
|
|
239
|
-
|
240
|
-
|
303
|
+
if record.present?
|
304
|
+
@record = record
|
241
305
|
|
242
|
-
|
243
|
-
|
306
|
+
hydrate_model_with_default_values if @view == :new
|
307
|
+
end
|
244
308
|
|
245
|
-
self
|
309
|
+
self
|
246
310
|
end
|
247
311
|
|
248
312
|
def default_panel_name
|
@@ -258,86 +322,59 @@ module Avo
|
|
258
322
|
end
|
259
323
|
end
|
260
324
|
|
325
|
+
# Returns the model class being used for this resource.
|
326
|
+
#
|
327
|
+
# We use the class method as a fallback but we pass it the record too so it can support the STI use cases
|
328
|
+
# where we figure out the model class from that record.
|
261
329
|
def model_class
|
262
|
-
|
263
|
-
return self.class.model_class if self.class.model_class.present?
|
330
|
+
record_class = @record&.class
|
264
331
|
|
265
|
-
|
266
|
-
return @record.base_class if @record.present?
|
267
|
-
|
268
|
-
# generate a model class
|
269
|
-
class_name.safe_constantize
|
332
|
+
self.class.model_class record_class: record_class
|
270
333
|
end
|
271
334
|
|
272
335
|
def record_title
|
273
336
|
return name if @record.nil?
|
274
337
|
|
275
|
-
|
276
|
-
return
|
338
|
+
# Get the title from the record if title is not set, try to get the name, title or label, or fallback to the id
|
339
|
+
return @record.try(:name) || @record.try(:title) || @record.try(:label) || @record.id if title.nil?
|
277
340
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
self.class.translation_key || "avo.resource_translations.#{class_name.underscore}"
|
285
|
-
end
|
286
|
-
|
287
|
-
def name
|
288
|
-
default = class_name.underscore.humanize
|
289
|
-
|
290
|
-
return @name if @name.present?
|
291
|
-
|
292
|
-
if translation_key
|
293
|
-
t(translation_key, count: 1, default: default).capitalize
|
294
|
-
else
|
295
|
-
default
|
341
|
+
# If the title is a symbol, get the value from the record else execute the block/string
|
342
|
+
case title
|
343
|
+
when Symbol
|
344
|
+
@record.send title
|
345
|
+
when Proc
|
346
|
+
Avo::ExecutionContext.new(target: title, resource: self, record: @record).handle
|
296
347
|
end
|
297
348
|
end
|
298
349
|
|
299
|
-
def
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
else
|
309
|
-
default
|
350
|
+
def available_view_types
|
351
|
+
if self.class.view_types.present?
|
352
|
+
return Array(
|
353
|
+
Avo::ExecutionContext.new(
|
354
|
+
target: self.class.view_types,
|
355
|
+
resource: self,
|
356
|
+
record: record
|
357
|
+
).handle
|
358
|
+
)
|
310
359
|
end
|
311
|
-
end
|
312
|
-
|
313
|
-
def underscore_name
|
314
|
-
return @name if @name.present?
|
315
|
-
|
316
|
-
self.class.name.demodulize.underscore
|
317
|
-
end
|
318
|
-
|
319
|
-
def navigation_label
|
320
|
-
plural_name.humanize
|
321
|
-
end
|
322
360
|
|
323
|
-
def available_view_types
|
324
361
|
view_types = [:table]
|
325
362
|
|
326
|
-
view_types << :grid if
|
363
|
+
view_types << :grid if self.class.grid_view.present?
|
327
364
|
view_types << :map if map_view.present?
|
328
365
|
|
329
366
|
view_types
|
330
367
|
end
|
331
368
|
|
332
|
-
def
|
369
|
+
def attachment_fields
|
333
370
|
get_field_definitions.select do |field|
|
334
371
|
[Avo::Fields::FileField, Avo::Fields::FilesField].include? field.class
|
335
372
|
end
|
336
373
|
end
|
337
374
|
|
338
|
-
|
339
|
-
|
340
|
-
|
375
|
+
# Map the received params to their actual fields
|
376
|
+
def fields_by_database_id
|
377
|
+
get_field_definitions
|
341
378
|
.reject do |field|
|
342
379
|
field.computed
|
343
380
|
end
|
@@ -345,7 +382,9 @@ module Avo
|
|
345
382
|
[field.database_id.to_s, field]
|
346
383
|
end
|
347
384
|
.to_h
|
385
|
+
end
|
348
386
|
|
387
|
+
def fill_record(record, params, extra_params: [])
|
349
388
|
# Write the field values
|
350
389
|
params.each do |key, value|
|
351
390
|
field = fields_by_database_id[key]
|
@@ -402,20 +441,18 @@ module Avo
|
|
402
441
|
!field.computed
|
403
442
|
end
|
404
443
|
.map do |field|
|
405
|
-
id = field.id
|
406
444
|
value = field.value
|
407
445
|
|
408
446
|
if field.type == "belongs_to"
|
409
|
-
id = field.foreign_key.to_sym
|
410
447
|
|
411
448
|
reflection = @record._reflections[@params[:via_relation]]
|
412
449
|
|
413
450
|
if field.polymorphic_as.present? && field.types.map(&:to_s).include?(@params[:via_relation_class])
|
414
451
|
# set the value to the actual record
|
415
|
-
via_resource = Avo
|
452
|
+
via_resource = Avo.resource_manager.get_resource_by_model_class(@params[:via_relation_class])
|
416
453
|
value = via_resource.find_record(@params[:via_record_id])
|
417
454
|
elsif reflection.present? && reflection.foreign_key.present? && field.id.to_s == @params[:via_relation].to_s
|
418
|
-
resource = Avo
|
455
|
+
resource = Avo.resource_manager.get_resource_by_model_class params[:via_relation_class]
|
419
456
|
record = resource.find_record @params[:via_record_id], params: params
|
420
457
|
id_param = reflection.options[:primary_key] || :id
|
421
458
|
|
@@ -423,28 +460,18 @@ module Avo
|
|
423
460
|
end
|
424
461
|
end
|
425
462
|
|
426
|
-
[
|
463
|
+
[field, value]
|
427
464
|
end
|
428
465
|
.to_h
|
429
|
-
.select do |
|
466
|
+
.select do |_, value|
|
430
467
|
value.present?
|
431
468
|
end
|
432
469
|
|
433
|
-
default_values.each do |
|
434
|
-
|
435
|
-
@record.send("#{id}=", value)
|
436
|
-
end
|
470
|
+
default_values.each do |field, value|
|
471
|
+
field.assign_value record: @record, value: value
|
437
472
|
end
|
438
473
|
end
|
439
474
|
|
440
|
-
# This is used as the model class ID
|
441
|
-
# We use this instead of the route_key to maintain compatibility with uncountable models
|
442
|
-
# With uncountable models route key appends an _index suffix (Fish->fish_index)
|
443
|
-
# Example: User->users, MediaItem->media_items, Fish->fish
|
444
|
-
def model_key
|
445
|
-
model_class.model_name.plural
|
446
|
-
end
|
447
|
-
|
448
475
|
def model_name
|
449
476
|
model_class.model_name
|
450
477
|
end
|
@@ -461,18 +488,6 @@ module Avo
|
|
461
488
|
resources_path(resource: self)
|
462
489
|
end
|
463
490
|
|
464
|
-
def label_field
|
465
|
-
get_field_definitions.find do |field|
|
466
|
-
field.as_label.present?
|
467
|
-
end
|
468
|
-
rescue
|
469
|
-
nil
|
470
|
-
end
|
471
|
-
|
472
|
-
def label
|
473
|
-
label_field&.value || record_title
|
474
|
-
end
|
475
|
-
|
476
491
|
def avatar_field
|
477
492
|
get_field_definitions.find do |field|
|
478
493
|
field.as_avatar.present?
|
@@ -497,18 +512,6 @@ module Avo
|
|
497
512
|
nil
|
498
513
|
end
|
499
514
|
|
500
|
-
def description_field
|
501
|
-
get_field_definitions.find do |field|
|
502
|
-
field.as_description.present?
|
503
|
-
end
|
504
|
-
rescue
|
505
|
-
nil
|
506
|
-
end
|
507
|
-
|
508
|
-
def search_description
|
509
|
-
description_field&.value
|
510
|
-
end
|
511
|
-
|
512
515
|
def form_scope
|
513
516
|
model_class.base_class.to_s.underscore.downcase
|
514
517
|
end
|
@@ -517,15 +520,6 @@ module Avo
|
|
517
520
|
record.present? && record_id.present?
|
518
521
|
end
|
519
522
|
|
520
|
-
def find_record(id, query: nil, params: nil)
|
521
|
-
Avo::ExecutionContext.new(
|
522
|
-
target: self.class.find_record_method,
|
523
|
-
query: query || self.class.find_scope,
|
524
|
-
id: id,
|
525
|
-
params: params
|
526
|
-
).handle
|
527
|
-
end
|
528
|
-
|
529
523
|
def id_attribute
|
530
524
|
:id
|
531
525
|
end
|
@@ -541,5 +535,11 @@ module Avo
|
|
541
535
|
record: record
|
542
536
|
}
|
543
537
|
end
|
538
|
+
|
539
|
+
private
|
540
|
+
|
541
|
+
def entity_loader(entity)
|
542
|
+
instance_variable_get("@#{entity.to_s.pluralize}_loader")
|
543
|
+
end
|
544
544
|
end
|
545
545
|
end
|