avo 3.0.0.pre12 → 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.
- 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/index/resource_table_component.rb +1 -1
- 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 +16 -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 +39 -27
- 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 +3 -6
- 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 -3
- data/lib/avo/base_resource.rb +183 -181
- 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 +29 -2
- 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/execution_context.rb +1 -1
- 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/filters/base_filter.rb +3 -1
- data/lib/avo/html/builder.rb +3 -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
@@ -10,7 +10,7 @@
|
|
10
10
|
<%= render partial: "avo/partials/logo" %>
|
11
11
|
</div>
|
12
12
|
<div class="flex-1 flex items-center justify-between lg:justify-start space-x-2 sm:space-x-8 lg:px-2">
|
13
|
-
<%= render
|
13
|
+
<%= render Avo::Pro::GlobalSearchComponent.new rescue nil %>
|
14
14
|
<div class="m-0">
|
15
15
|
<%= render partial: "avo/partials/header" %>
|
16
16
|
</div>
|
@@ -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
@@ -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
|
-
|
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
|
@@ -86,7 +88,14 @@ module Avo
|
|
86
88
|
|
87
89
|
def get_attributes_for_action
|
88
90
|
get_fields.map do |field|
|
89
|
-
|
91
|
+
value = field.value || Avo::ExecutionContext.new(
|
92
|
+
target: field.default,
|
93
|
+
record: self.class.record,
|
94
|
+
resource: self.class.resource,
|
95
|
+
view: view
|
96
|
+
).handle
|
97
|
+
|
98
|
+
[field.id, value]
|
90
99
|
end.to_h
|
91
100
|
end
|
92
101
|
|
@@ -121,7 +130,7 @@ module Avo
|
|
121
130
|
resource: resource
|
122
131
|
}
|
123
132
|
|
124
|
-
args[:records] = records
|
133
|
+
args[:records] = records
|
125
134
|
|
126
135
|
handle(**args)
|
127
136
|
|
data/lib/avo/base_resource.rb
CHANGED
@@ -12,7 +12,9 @@ module Avo
|
|
12
12
|
|
13
13
|
# Avo::Current methods
|
14
14
|
delegate :context, to: Avo::Current
|
15
|
-
|
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
|
@@ -38,19 +40,17 @@ module Avo
|
|
38
40
|
attr_accessor :record
|
39
41
|
|
40
42
|
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
|
43
|
+
class_attribute :title
|
44
|
+
class_attribute :search, default: {}
|
45
45
|
class_attribute :includes, default: []
|
46
46
|
class_attribute :authorization_policy
|
47
47
|
class_attribute :translation_key
|
48
48
|
class_attribute :default_view_type, default: :table
|
49
49
|
class_attribute :devise_password_optional, default: false
|
50
|
-
class_attribute :actions_loader
|
51
50
|
class_attribute :scopes_loader
|
52
51
|
class_attribute :filters_loader
|
53
|
-
class_attribute :
|
52
|
+
class_attribute :view_types
|
53
|
+
class_attribute :grid_view
|
54
54
|
class_attribute :visible_on_sidebar, default: true
|
55
55
|
class_attribute :index_query, default: -> {
|
56
56
|
query
|
@@ -58,7 +58,6 @@ module Avo
|
|
58
58
|
class_attribute :find_record_method, default: -> {
|
59
59
|
query.find id
|
60
60
|
}
|
61
|
-
class_attribute :hide_from_global_search, default: false
|
62
61
|
class_attribute :after_create_path, default: :show
|
63
62
|
class_attribute :after_update_path, default: :show
|
64
63
|
class_attribute :record_selector, default: true
|
@@ -74,42 +73,21 @@ module Avo
|
|
74
73
|
delegate :t, to: ::I18n
|
75
74
|
delegate :context, to: ::Avo::Current
|
76
75
|
|
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
76
|
def action(action_class, arguments: {})
|
85
|
-
|
86
|
-
|
87
|
-
action = {class: action_class, arguments: arguments}
|
88
|
-
self.actions_loader.use action
|
77
|
+
deprecated_dsl_api __method__, "actions"
|
89
78
|
end
|
90
79
|
|
91
80
|
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
|
81
|
+
deprecated_dsl_api __method__, "filters"
|
102
82
|
end
|
103
83
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
args.each do |scope_class|
|
108
|
-
self.scopes_loader.use scope_class
|
109
|
-
end
|
84
|
+
def scope(scope_class)
|
85
|
+
deprecated_dsl_api __method__, "scopes"
|
110
86
|
end
|
111
87
|
|
112
88
|
# This resolves the scope when doing "where" queries (not find queries)
|
89
|
+
#
|
90
|
+
# It's used to apply the authorization feature.
|
113
91
|
def query_scope
|
114
92
|
authorization.apply_policy Avo::ExecutionContext.new(
|
115
93
|
target: index_query,
|
@@ -118,12 +96,14 @@ module Avo
|
|
118
96
|
end
|
119
97
|
|
120
98
|
# This resolves the scope when finding records (not "where" queries)
|
99
|
+
#
|
100
|
+
# It's used to apply the authorization feature.
|
121
101
|
def find_scope
|
122
102
|
authorization.apply_policy model_class
|
123
103
|
end
|
124
104
|
|
125
105
|
def authorization
|
126
|
-
Avo::Services::AuthorizationService.new Avo::Current.
|
106
|
+
Avo::Services::AuthorizationService.new Avo::Current.user, model_class, policy_class: authorization_policy
|
127
107
|
end
|
128
108
|
|
129
109
|
def get_record_associations(record)
|
@@ -153,8 +133,31 @@ module Avo
|
|
153
133
|
end
|
154
134
|
end
|
155
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
|
+
|
156
159
|
def class_name
|
157
|
-
|
160
|
+
to_s.demodulize
|
158
161
|
end
|
159
162
|
|
160
163
|
def route_key
|
@@ -164,11 +167,81 @@ module Avo
|
|
164
167
|
def singular_route_key
|
165
168
|
route_key.singularize
|
166
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
|
167
223
|
end
|
168
224
|
|
169
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
|
170
244
|
|
171
|
-
def initialize
|
172
245
|
detect_fields
|
173
246
|
|
174
247
|
unless self.class.model_class.present?
|
@@ -195,54 +268,47 @@ module Avo
|
|
195
268
|
# blank fields method
|
196
269
|
end
|
197
270
|
|
198
|
-
|
199
|
-
|
200
|
-
@user = user if user.present?
|
201
|
-
@params = params if params.present?
|
202
|
-
|
203
|
-
if record.present?
|
204
|
-
@record = record
|
271
|
+
[:action, :filter, :scope].each do |entity|
|
272
|
+
plural_entity = entity.to_s.pluralize
|
205
273
|
|
206
|
-
|
274
|
+
# def actions / def filters / def scopes
|
275
|
+
define_method plural_entity do
|
276
|
+
# blank entity method
|
207
277
|
end
|
208
278
|
|
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
|
279
|
+
# def action / def filter / def scope
|
280
|
+
define_method entity do |entity_class, arguments: {}|
|
281
|
+
entity_loader(entity).use({class: entity_class, arguments: arguments})
|
282
|
+
end
|
223
283
|
|
224
|
-
|
225
|
-
|
284
|
+
# def get_actions / def get_filters / def get_scopes
|
285
|
+
define_method "get_#{plural_entity}" do
|
286
|
+
return entity_loader(entity).bag if entity_loader(entity).present?
|
226
287
|
|
227
|
-
|
228
|
-
|
288
|
+
instance_variable_set("@#{plural_entity}_loader", Avo::Loaders::Loader.new)
|
289
|
+
send plural_entity
|
229
290
|
|
230
|
-
|
231
|
-
|
291
|
+
entity_loader(entity).bag
|
292
|
+
end
|
232
293
|
|
233
|
-
|
294
|
+
# def get_action_arguments / def get_filter_arguments / def get_scope_arguments
|
295
|
+
define_method "get_#{entity}_arguments" do |entity_class|
|
296
|
+
send("get_#{plural_entity}").find { |entity| entity[:class].to_s == entity_class.to_s }[:arguments]
|
297
|
+
end
|
234
298
|
end
|
235
299
|
|
236
|
-
def
|
237
|
-
|
300
|
+
def hydrate(record: nil, view: nil, user: nil, params: nil)
|
301
|
+
@view = view if view.present?
|
302
|
+
@user = user if user.present?
|
303
|
+
@params = params if params.present?
|
238
304
|
|
239
|
-
|
240
|
-
|
305
|
+
if record.present?
|
306
|
+
@record = record
|
241
307
|
|
242
|
-
|
243
|
-
|
308
|
+
hydrate_model_with_default_values if @view == :new
|
309
|
+
end
|
244
310
|
|
245
|
-
self
|
311
|
+
self
|
246
312
|
end
|
247
313
|
|
248
314
|
def default_panel_name
|
@@ -258,86 +324,59 @@ module Avo
|
|
258
324
|
end
|
259
325
|
end
|
260
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.
|
261
331
|
def model_class
|
262
|
-
|
263
|
-
return self.class.model_class if self.class.model_class.present?
|
332
|
+
record_class = @record&.class
|
264
333
|
|
265
|
-
|
266
|
-
return @record.base_class if @record.present?
|
267
|
-
|
268
|
-
# generate a model class
|
269
|
-
class_name.safe_constantize
|
334
|
+
self.class.model_class record_class: record_class
|
270
335
|
end
|
271
336
|
|
272
337
|
def record_title
|
273
338
|
return name if @record.nil?
|
274
339
|
|
275
|
-
|
276
|
-
return
|
340
|
+
# Get the title from the record if title is not set, try to get the name, title or label, or fallback to the id
|
341
|
+
return @record.try(:name) || @record.try(:title) || @record.try(:label) || @record.id if title.nil?
|
277
342
|
|
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
|
343
|
+
# If the title is a symbol, get the value from the record else execute the block/string
|
344
|
+
case title
|
345
|
+
when Symbol
|
346
|
+
@record.send title
|
347
|
+
when Proc
|
348
|
+
Avo::ExecutionContext.new(target: title, resource: self, record: @record).handle
|
296
349
|
end
|
297
350
|
end
|
298
351
|
|
299
|
-
def
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
else
|
309
|
-
default
|
352
|
+
def available_view_types
|
353
|
+
if self.class.view_types.present?
|
354
|
+
return Array(
|
355
|
+
Avo::ExecutionContext.new(
|
356
|
+
target: self.class.view_types,
|
357
|
+
resource: self,
|
358
|
+
record: record
|
359
|
+
).handle
|
360
|
+
)
|
310
361
|
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
362
|
|
323
|
-
def available_view_types
|
324
363
|
view_types = [:table]
|
325
364
|
|
326
|
-
view_types << :grid if
|
365
|
+
view_types << :grid if self.class.grid_view.present?
|
327
366
|
view_types << :map if map_view.present?
|
328
367
|
|
329
368
|
view_types
|
330
369
|
end
|
331
370
|
|
332
|
-
def
|
371
|
+
def attachment_fields
|
333
372
|
get_field_definitions.select do |field|
|
334
373
|
[Avo::Fields::FileField, Avo::Fields::FilesField].include? field.class
|
335
374
|
end
|
336
375
|
end
|
337
376
|
|
338
|
-
|
339
|
-
|
340
|
-
|
377
|
+
# Map the received params to their actual fields
|
378
|
+
def fields_by_database_id
|
379
|
+
get_field_definitions
|
341
380
|
.reject do |field|
|
342
381
|
field.computed
|
343
382
|
end
|
@@ -345,7 +384,9 @@ module Avo
|
|
345
384
|
[field.database_id.to_s, field]
|
346
385
|
end
|
347
386
|
.to_h
|
387
|
+
end
|
348
388
|
|
389
|
+
def fill_record(record, params, extra_params: [])
|
349
390
|
# Write the field values
|
350
391
|
params.each do |key, value|
|
351
392
|
field = fields_by_database_id[key]
|
@@ -365,7 +406,7 @@ module Avo
|
|
365
406
|
end
|
366
407
|
|
367
408
|
def authorization(user: nil)
|
368
|
-
current_user = user || Avo::Current.
|
409
|
+
current_user = user || Avo::Current.user
|
369
410
|
Avo::Services::AuthorizationService.new(current_user, record || model_class, policy_class: authorization_policy)
|
370
411
|
end
|
371
412
|
|
@@ -402,20 +443,18 @@ module Avo
|
|
402
443
|
!field.computed
|
403
444
|
end
|
404
445
|
.map do |field|
|
405
|
-
id = field.id
|
406
446
|
value = field.value
|
407
447
|
|
408
448
|
if field.type == "belongs_to"
|
409
|
-
id = field.foreign_key.to_sym
|
410
449
|
|
411
450
|
reflection = @record._reflections[@params[:via_relation]]
|
412
451
|
|
413
452
|
if field.polymorphic_as.present? && field.types.map(&:to_s).include?(@params[:via_relation_class])
|
414
453
|
# set the value to the actual record
|
415
|
-
via_resource = Avo
|
454
|
+
via_resource = Avo.resource_manager.get_resource_by_model_class(@params[:via_relation_class])
|
416
455
|
value = via_resource.find_record(@params[:via_record_id])
|
417
456
|
elsif reflection.present? && reflection.foreign_key.present? && field.id.to_s == @params[:via_relation].to_s
|
418
|
-
resource = Avo
|
457
|
+
resource = Avo.resource_manager.get_resource_by_model_class params[:via_relation_class]
|
419
458
|
record = resource.find_record @params[:via_record_id], params: params
|
420
459
|
id_param = reflection.options[:primary_key] || :id
|
421
460
|
|
@@ -423,28 +462,18 @@ module Avo
|
|
423
462
|
end
|
424
463
|
end
|
425
464
|
|
426
|
-
[
|
465
|
+
[field, value]
|
427
466
|
end
|
428
467
|
.to_h
|
429
|
-
.select do |
|
468
|
+
.select do |_, value|
|
430
469
|
value.present?
|
431
470
|
end
|
432
471
|
|
433
|
-
default_values.each do |
|
434
|
-
|
435
|
-
@record.send("#{id}=", value)
|
436
|
-
end
|
472
|
+
default_values.each do |field, value|
|
473
|
+
field.assign_value record: @record, value: value
|
437
474
|
end
|
438
475
|
end
|
439
476
|
|
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
477
|
def model_name
|
449
478
|
model_class.model_name
|
450
479
|
end
|
@@ -461,18 +490,6 @@ module Avo
|
|
461
490
|
resources_path(resource: self)
|
462
491
|
end
|
463
492
|
|
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
493
|
def avatar_field
|
477
494
|
get_field_definitions.find do |field|
|
478
495
|
field.as_avatar.present?
|
@@ -497,18 +514,6 @@ module Avo
|
|
497
514
|
nil
|
498
515
|
end
|
499
516
|
|
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
517
|
def form_scope
|
513
518
|
model_class.base_class.to_s.underscore.downcase
|
514
519
|
end
|
@@ -517,15 +522,6 @@ module Avo
|
|
517
522
|
record.present? && record_id.present?
|
518
523
|
end
|
519
524
|
|
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
525
|
def id_attribute
|
530
526
|
:id
|
531
527
|
end
|
@@ -541,5 +537,11 @@ module Avo
|
|
541
537
|
record: record
|
542
538
|
}
|
543
539
|
end
|
540
|
+
|
541
|
+
private
|
542
|
+
|
543
|
+
def entity_loader(entity)
|
544
|
+
instance_variable_get("@#{entity.to_s.pluralize}_loader")
|
545
|
+
end
|
544
546
|
end
|
545
547
|
end
|