avo 3.0.0.beta1 → 3.0.0.pre1
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 +5 -5
- data/Gemfile.lock +81 -92
- data/{public/avo-assets/avo.css → app/assets/builds/avo.base.css} +686 -728
- data/app/assets/builds/avo.base.js +93804 -0
- data/app/assets/builds/avo.base.js.map +7 -0
- data/app/assets/stylesheets/avo.base.css +2 -1
- data/app/assets/svgs/failed_to_load.svg +1 -0
- data/app/assets/svgs/grid-empty-state.svg +1 -0
- data/app/assets/svgs/table-empty-state.svg +1 -0
- data/app/assets/svgs/triangle-up.svg +1 -1
- data/app/components/avo/actions_component.html.erb +1 -1
- data/app/components/avo/actions_component.rb +16 -42
- 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 +4 -4
- data/app/components/avo/field_wrapper_component.rb +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 -8
- data/app/components/avo/fields/boolean_field/edit_component.html.erb +0 -1
- 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 +0 -1
- data/app/components/avo/fields/common/files_list_viewer_component.html.erb +5 -0
- data/app/components/avo/fields/common/files_list_viewer_component.rb +8 -0
- data/app/components/avo/fields/common/heading_component.html.erb +1 -1
- data/app/components/avo/fields/common/single_file_viewer_component.html.erb +56 -0
- data/app/components/avo/fields/common/single_file_viewer_component.rb +55 -0
- data/app/components/avo/fields/country_field/edit_component.html.erb +1 -3
- data/app/components/avo/fields/file_field/edit_component.html.erb +2 -4
- data/app/components/avo/fields/file_field/edit_component.rb +0 -1
- data/app/components/avo/fields/file_field/index_component.rb +2 -2
- data/app/components/avo/fields/file_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/files_field/edit_component.html.erb +2 -4
- data/app/components/avo/fields/files_field/edit_component.rb +0 -1
- data/app/components/avo/fields/files_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/has_many_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/has_one_field/show_component.html.erb +4 -5
- data/app/components/avo/fields/has_one_field/show_component.rb +2 -6
- data/app/components/avo/fields/index_component.rb +0 -1
- data/app/components/avo/fields/markdown_field/edit_component.html.erb +3 -4
- 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 -3
- data/app/components/avo/fields/password_field/edit_component.html.erb +1 -3
- data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +0 -1
- data/app/components/avo/fields/select_field/edit_component.html.erb +1 -2
- data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/text_field/edit_component.html.erb +2 -3
- data/app/components/avo/fields/textarea_field/edit_component.html.erb +0 -1
- data/app/components/avo/fields/trix_field/edit_component.html.erb +1 -2
- 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/field_wrapper_component.rb +12 -0
- data/app/components/avo/index/grid_item_component.html.erb +35 -9
- data/app/components/avo/index/grid_item_component.rb +10 -36
- data/app/components/avo/index/resource_controls_component.rb +11 -8
- data/app/components/avo/index/resource_table_component.rb +1 -1
- data/app/components/avo/item_switcher_component.html.erb +5 -10
- data/app/components/avo/item_switcher_component.rb +1 -2
- data/app/components/avo/modal_component.html.erb +1 -1
- data/app/components/avo/panel_component.html.erb +1 -6
- data/app/components/avo/panel_component.rb +0 -1
- data/app/components/avo/profile_item_component.html.erb +2 -17
- data/app/components/avo/profile_item_component.rb +1 -13
- data/app/components/avo/referrer_params_component.html.erb +0 -2
- data/app/components/avo/resource_component.rb +6 -69
- data/app/components/avo/resource_sidebar_component.rb +1 -1
- data/app/components/avo/sidebar/link_component.html.erb +0 -2
- data/app/components/avo/sidebar/link_component.rb +3 -5
- 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.html.erb +5 -5
- data/app/components/avo/views/resource_edit_component.rb +1 -1
- data/app/components/avo/views/resource_index_component.html.erb +10 -19
- data/app/components/avo/views/resource_index_component.rb +16 -22
- data/app/components/avo/views/resource_show_component.html.erb +4 -4
- data/app/controllers/avo/actions_controller.rb +20 -20
- data/app/controllers/avo/application_controller.rb +67 -90
- data/app/controllers/avo/associations_controller.rb +7 -5
- data/app/controllers/avo/attachments_controller.rb +7 -22
- data/app/controllers/avo/base_controller.rb +35 -47
- data/app/controllers/avo/home_controller.rb +1 -1
- data/app/controllers/avo/search_controller.rb +16 -20
- data/app/controllers/concerns/avo/initializes_avo.rb +8 -3
- data/app/helpers/avo/application_helper.rb +6 -13
- data/app/javascript/js/application.js +0 -2
- data/app/javascript/js/controllers/fields/{easy_mde_controller.js → simple_mde_controller.js} +3 -4
- data/app/javascript/js/controllers/search_controller.js +1 -3
- data/app/javascript/js/controllers.js +2 -2
- data/app/views/avo/actions/show.html.erb +3 -5
- data/app/views/avo/associations/new.html.erb +3 -3
- data/app/views/avo/debug/status.html.erb +5 -6
- data/app/views/avo/home/index.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/_table_header.html.erb +8 -0
- data/app/views/avo/partials/_view_toggle_button.html.erb +0 -9
- data/app/views/avo/private/design.html.erb +2 -2
- data/app/views/layouts/avo/application.html.erb +3 -2
- data/avo.gemspec +1 -2
- data/config/initializers/pagy.rb +10 -12
- data/config/routes.rb +5 -5
- data/db/factories.rb +0 -17
- data/lib/avo/app.rb +165 -0
- data/lib/avo/base_action.rb +18 -31
- data/lib/avo/base_resource.rb +213 -238
- data/lib/avo/concerns/breadcrumbs.rb +2 -2
- data/lib/avo/concerns/can_replace_items.rb +7 -3
- data/lib/avo/concerns/filters_session_handler.rb +4 -5
- data/lib/avo/concerns/has_item_type.rb +0 -4
- data/lib/avo/concerns/has_items.rb +115 -93
- data/lib/avo/concerns/is_visible.rb +1 -1
- data/lib/avo/concerns/model_class_constantized.rb +2 -0
- data/lib/avo/configuration.rb +8 -9
- data/lib/avo/current.rb +1 -35
- data/lib/avo/dsl/field_parser.rb +1 -1
- data/lib/avo/dynamic_router.rb +2 -13
- data/lib/avo/engine.rb +13 -11
- data/lib/avo/execution_context.rb +2 -4
- data/lib/avo/fields/base_field.rb +14 -51
- data/lib/avo/fields/belongs_to_field.rb +13 -20
- data/lib/avo/fields/concerns/is_searchable.rb +1 -1
- data/lib/avo/fields/concerns/use_resource.rb +1 -1
- data/lib/avo/fields/date_field.rb +3 -16
- data/lib/avo/fields/field_manager.rb +3 -13
- data/lib/avo/fields/file_field.rb +0 -2
- data/lib/avo/fields/files_field.rb +0 -6
- data/lib/avo/fields/has_base_field.rb +5 -5
- data/lib/avo/fields/has_one_field.rb +1 -2
- data/lib/avo/fields/id_field.rb +1 -2
- data/lib/avo/filters/base_filter.rb +0 -9
- data/lib/avo/grid_collector.rb +40 -0
- data/lib/avo/html/builder.rb +1 -3
- data/lib/avo/licensing/h_q.rb +6 -11
- data/lib/avo/licensing/license.rb +1 -1
- data/lib/avo/licensing/license_manager.rb +1 -1
- data/lib/avo/licensing/{nil_license.rb → null_license.rb} +1 -1
- data/lib/avo/loaders/fields_loader.rb +1 -7
- data/lib/avo/plugin.rb +0 -10
- data/lib/avo/plugin_manager.rb +4 -2
- data/lib/avo/reloader.rb +1 -1
- data/lib/avo/resources/controls/actions_list.rb +1 -2
- data/lib/avo/resources/controls/create_button.rb +1 -1
- data/lib/avo/resources/controls/delete_button.rb +1 -1
- data/lib/avo/resources/controls/detach_button.rb +1 -1
- data/lib/avo/resources/controls/edit_button.rb +1 -1
- data/lib/avo/resources/controls/show_button.rb +1 -1
- data/lib/avo/resources/items/holder.rb +5 -13
- data/lib/avo/resources/items/item_group.rb +0 -1
- data/lib/avo/resources/resource_manager.rb +18 -11
- data/lib/avo/services/debug_service.rb +5 -6
- data/lib/avo/services/telemetry_service.rb +2 -3
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +25 -109
- data/lib/generators/avo/action_generator.rb +8 -8
- 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/eject_generator.rb +0 -1
- data/lib/generators/avo/filter_generator.rb +8 -8
- data/lib/generators/avo/install_generator.rb +1 -11
- data/lib/generators/avo/resource_generator.rb +4 -22
- data/lib/generators/avo/tailwindcss/install_generator.rb +1 -4
- data/lib/generators/avo/templates/action.tt +5 -7
- 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 +3 -5
- data/lib/generators/avo/templates/initializer/avo.tt +2 -4
- data/lib/generators/avo/templates/resource/resource.tt +6 -6
- data/lib/generators/avo/templates/scope.tt +1 -1
- data/lib/generators/avo/templates/standalone_action.tt +8 -0
- data/lib/generators/avo/templates/tailwindcss/Procfile.dev +1 -1
- data/lib/tasks/avo_tasks.rake +0 -5
- metadata +19 -56
- data/app/assets/svgs/map-empty-state.svg +0 -35
- data/app/assets/svgs/map-view-type.svg +0 -3
- data/app/components/avo/fields/area_field/edit_component.html.erb +0 -7
- data/app/components/avo/fields/area_field/edit_component.rb +0 -4
- data/app/components/avo/fields/area_field/show_component.html.erb +0 -8
- data/app/components/avo/fields/area_field/show_component.rb +0 -4
- data/app/components/avo/fields/common/files/controls_component.html.erb +0 -29
- data/app/components/avo/fields/common/files/controls_component.rb +0 -19
- data/app/components/avo/fields/common/files/list_viewer_component.html.erb +0 -20
- data/app/components/avo/fields/common/files/list_viewer_component.rb +0 -41
- data/app/components/avo/fields/common/files/view_type/grid_component.html.erb +0 -27
- data/app/components/avo/fields/common/files/view_type/grid_component.rb +0 -51
- data/app/components/avo/fields/common/files/view_type/list_component.html.erb +0 -22
- data/app/components/avo/fields/common/files/view_type/list_component.rb +0 -15
- data/app/components/avo/fields/location_field/edit_component.html.erb +0 -22
- data/app/components/avo/fields/location_field/edit_component.rb +0 -4
- data/app/components/avo/fields/location_field/show_component.html.erb +0 -7
- data/app/components/avo/fields/location_field/show_component.rb +0 -4
- data/app/components/avo/index/resource_map_component.html.erb +0 -16
- data/app/components/avo/index/resource_map_component.rb +0 -109
- data/app/components/avo/row_component.html.erb +0 -3
- data/app/components/avo/row_component.rb +0 -12
- data/app/views/avo/attachments/destroy.turbo_stream.erb +0 -7
- data/app/views/avo/partials/_profile_menu_extra.html.erb +0 -2
- data/lib/avo/concerns/has_description.rb +0 -23
- data/lib/avo/fields/area_field.rb +0 -39
- data/lib/avo/fields/concerns/file_authorization.rb +0 -31
- data/lib/avo/fields/location_field.rb +0 -86
- data/lib/avo/resources/items/row.rb +0 -54
- data/lib/generators/avo/card_generator.rb +0 -27
- data/public/avo-assets/avo.base.css +0 -10542
- data/public/avo-assets/avo.base.js +0 -949
- data/public/avo-assets/avo.base.js.map +0 -7
- data/public/avo-assets/avo.js +0 -513
- data/public/avo-assets/avo.js.map +0 -7
data/lib/avo/base_resource.rb
CHANGED
@@ -8,63 +8,54 @@ module Avo
|
|
8
8
|
include Avo::Concerns::HasControls
|
9
9
|
include Avo::Concerns::HasStimulusControllers
|
10
10
|
include Avo::Concerns::ModelClassConstantized
|
11
|
-
include Avo::Concerns::HasDescription
|
12
11
|
|
13
|
-
# Avo::Current methods
|
14
12
|
delegate :context, to: Avo::Current
|
15
|
-
|
16
|
-
Avo::Current.user
|
17
|
-
end
|
13
|
+
delegate :current_user, to: Avo::Current
|
18
14
|
delegate :params, to: Avo::Current
|
19
15
|
delegate :request, to: Avo::Current
|
20
16
|
delegate :view_context, to: Avo::Current
|
21
|
-
|
22
|
-
# view_context methods
|
23
17
|
delegate :simple_format, :content_tag, to: :view_context
|
24
18
|
delegate :main_app, to: :view_context
|
25
19
|
delegate :avo, to: :view_context
|
26
20
|
delegate :resource_path, to: :view_context
|
27
21
|
delegate :resources_path, to: :view_context
|
28
|
-
|
29
|
-
# I18n methods
|
30
22
|
delegate :t, to: ::I18n
|
31
23
|
|
32
|
-
# class methods
|
33
|
-
delegate :class_name, to: :class
|
34
|
-
delegate :route_key, to: :class
|
35
|
-
delegate :singular_route_key, to: :class
|
36
|
-
|
37
24
|
attr_accessor :view
|
38
25
|
attr_accessor :reflection
|
39
26
|
attr_accessor :user
|
27
|
+
attr_accessor :params
|
40
28
|
attr_accessor :record
|
41
29
|
|
42
30
|
class_attribute :id, default: :id
|
43
|
-
class_attribute :title
|
44
|
-
class_attribute :
|
31
|
+
class_attribute :title, default: :id
|
32
|
+
class_attribute :description, default: :id
|
33
|
+
class_attribute :search_query, default: nil
|
34
|
+
class_attribute :search_query_help, default: ""
|
45
35
|
class_attribute :includes, default: []
|
46
36
|
class_attribute :authorization_policy
|
47
37
|
class_attribute :translation_key
|
48
38
|
class_attribute :default_view_type, default: :table
|
49
39
|
class_attribute :devise_password_optional, default: false
|
40
|
+
class_attribute :actions_loader
|
50
41
|
class_attribute :scopes_loader
|
51
42
|
class_attribute :filters_loader
|
52
|
-
class_attribute :
|
53
|
-
class_attribute :grid_view
|
43
|
+
class_attribute :grid_loader
|
54
44
|
class_attribute :visible_on_sidebar, default: true
|
55
|
-
class_attribute :
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
45
|
+
class_attribute :unscoped_queries_on_index, default: false
|
46
|
+
class_attribute :resolve_index_query
|
47
|
+
class_attribute :resolve_find_scope
|
48
|
+
# TODO: refactor this into a Host without args
|
49
|
+
class_attribute :find_record_method, default: ->(model_class:, id:, params:) {
|
50
|
+
model_class.find id
|
60
51
|
}
|
52
|
+
class_attribute :hide_from_global_search, default: false
|
61
53
|
class_attribute :after_create_path, default: :show
|
62
54
|
class_attribute :after_update_path, default: :show
|
63
55
|
class_attribute :record_selector, default: true
|
64
56
|
class_attribute :keep_filters_panel_open, default: false
|
65
57
|
class_attribute :extra_params
|
66
58
|
class_attribute :link_to_child_resource, default: false
|
67
|
-
class_attribute :map_view
|
68
59
|
|
69
60
|
# EXTRACT:
|
70
61
|
class_attribute :ordering
|
@@ -73,37 +64,65 @@ module Avo
|
|
73
64
|
delegate :t, to: ::I18n
|
74
65
|
delegate :context, to: ::Avo::Current
|
75
66
|
|
67
|
+
def grid(&block)
|
68
|
+
grid_collector = GridCollector.new
|
69
|
+
grid_collector.instance_eval(&block)
|
70
|
+
|
71
|
+
self.grid_loader = grid_collector
|
72
|
+
end
|
73
|
+
|
76
74
|
def action(action_class, arguments: {})
|
77
|
-
|
75
|
+
self.actions_loader ||= Avo::Loaders::Loader.new
|
76
|
+
|
77
|
+
action = {class: action_class, arguments: arguments}
|
78
|
+
self.actions_loader.use action
|
78
79
|
end
|
79
80
|
|
80
81
|
def filter(filter_class, arguments: {})
|
81
|
-
|
82
|
+
self.filters_loader ||= Avo::Loaders::Loader.new
|
83
|
+
|
84
|
+
filter = { class: filter_class , arguments: arguments }
|
85
|
+
self.filters_loader.use filter
|
82
86
|
end
|
83
87
|
|
84
|
-
|
85
|
-
|
88
|
+
# This is the search_query scope
|
89
|
+
# This should be removed and passed to the search block
|
90
|
+
def scope
|
91
|
+
query_scope
|
92
|
+
end
|
93
|
+
|
94
|
+
def scopes(*args)
|
95
|
+
self.scopes_loader ||= Avo::Loaders::Loader.new
|
96
|
+
|
97
|
+
args.each do |scope_class|
|
98
|
+
self.scopes_loader.use scope_class
|
99
|
+
end
|
86
100
|
end
|
87
101
|
|
88
102
|
# This resolves the scope when doing "where" queries (not find queries)
|
89
|
-
#
|
90
|
-
# It's used to apply the authorization feature.
|
91
103
|
def query_scope
|
92
|
-
|
93
|
-
target:
|
94
|
-
|
95
|
-
|
104
|
+
final_scope = if resolve_index_query.present?
|
105
|
+
Avo::ExecutionContext.new(target: resolve_index_query, model_class: model_class).handle
|
106
|
+
else
|
107
|
+
model_class
|
108
|
+
end
|
109
|
+
|
110
|
+
authorization.apply_policy final_scope
|
96
111
|
end
|
97
112
|
|
98
113
|
# This resolves the scope when finding records (not "where" queries)
|
99
|
-
#
|
100
|
-
# It's used to apply the authorization feature.
|
101
114
|
def find_scope
|
102
|
-
|
115
|
+
final_scope = if resolve_find_scope.present?
|
116
|
+
Avo::ExecutionContext.new(target: resolve_find_scope, model_class: model_class).handle
|
117
|
+
else
|
118
|
+
model_class
|
119
|
+
end
|
120
|
+
|
121
|
+
authorization.apply_policy final_scope
|
103
122
|
end
|
104
123
|
|
105
124
|
def authorization
|
106
|
-
Avo::Services::AuthorizationService.new Avo::Current.
|
125
|
+
Avo::Services::AuthorizationService.new Avo::Current.current_user, model_class, policy_class: authorization_policy
|
107
126
|
end
|
108
127
|
|
109
128
|
def get_record_associations(record)
|
@@ -132,106 +151,19 @@ module Avo
|
|
132
151
|
m.to_s == model_name.to_s
|
133
152
|
end
|
134
153
|
end
|
154
|
+
end
|
135
155
|
|
136
|
-
|
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
|
-
|
159
|
-
def class_name
|
160
|
-
to_s.demodulize
|
161
|
-
end
|
162
|
-
|
163
|
-
def route_key
|
164
|
-
class_name.underscore.pluralize
|
165
|
-
end
|
166
|
-
|
167
|
-
def singular_route_key
|
168
|
-
route_key.singularize
|
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).humanize
|
180
|
-
else
|
181
|
-
default
|
182
|
-
end
|
183
|
-
end
|
184
|
-
alias_method :singular_name, :name
|
185
|
-
|
186
|
-
def plural_name
|
187
|
-
default = name.pluralize
|
156
|
+
delegate :context, to: ::Avo::Current
|
188
157
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
158
|
+
def initialize
|
159
|
+
unless self.class.model_class.present?
|
160
|
+
if model_class.present? && model_class.respond_to?(:base_class)
|
161
|
+
self.class.model_class = model_class.base_class
|
193
162
|
end
|
194
163
|
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
|
223
164
|
end
|
224
165
|
|
225
|
-
|
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)
|
166
|
+
def hydrate(record: nil, view: nil, user: nil, params: nil)
|
235
167
|
@view = view if view.present?
|
236
168
|
@user = user if user.present?
|
237
169
|
@params = params if params.present?
|
@@ -242,73 +174,43 @@ module Avo
|
|
242
174
|
hydrate_model_with_default_values if @view == :new
|
243
175
|
end
|
244
176
|
|
245
|
-
detect_fields
|
246
|
-
|
247
|
-
unless self.class.model_class.present?
|
248
|
-
if model_class.present? && model_class.respond_to?(:base_class)
|
249
|
-
self.class.model_class = model_class.base_class
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
def detect_fields
|
255
|
-
self.items_holder = Avo::Resources::Items::Holder.new
|
256
|
-
|
257
|
-
# Used in testing to replace items
|
258
|
-
if temporary_items.present?
|
259
|
-
instance_eval(&temporary_items)
|
260
|
-
else
|
261
|
-
fields
|
262
|
-
end
|
263
|
-
|
264
177
|
self
|
265
178
|
end
|
266
179
|
|
267
|
-
def
|
268
|
-
|
269
|
-
end
|
180
|
+
def get_grid_fields
|
181
|
+
return if self.class.grid_loader.blank?
|
270
182
|
|
271
|
-
|
272
|
-
|
183
|
+
self.class.grid_loader.hydrate(record: @record, view: @view, resource: self)
|
184
|
+
end
|
273
185
|
|
274
|
-
|
275
|
-
|
276
|
-
# blank entity method
|
277
|
-
end
|
186
|
+
def get_filters
|
187
|
+
return [] if self.class.filters_loader.blank?
|
278
188
|
|
279
|
-
|
280
|
-
|
281
|
-
entity_loader(entity).use({class: entity_class, arguments: arguments})
|
282
|
-
end
|
189
|
+
self.class.filters_loader.bag
|
190
|
+
end
|
283
191
|
|
284
|
-
|
285
|
-
|
286
|
-
return entity_loader(entity).bag if entity_loader(entity).present?
|
192
|
+
def get_filter_arguments(filter_class)
|
193
|
+
filter = get_filters.find { |filter| filter[:class] == filter_class.constantize }
|
287
194
|
|
288
|
-
|
289
|
-
|
195
|
+
filter[:arguments]
|
196
|
+
end
|
290
197
|
|
291
|
-
|
292
|
-
|
198
|
+
def get_actions
|
199
|
+
return [] if self.class.actions_loader.blank?
|
293
200
|
|
294
|
-
|
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
|
201
|
+
self.class.actions_loader.bag
|
298
202
|
end
|
299
203
|
|
300
|
-
def
|
301
|
-
|
302
|
-
@user = user if user.present?
|
303
|
-
@params = params if params.present?
|
204
|
+
def get_action_arguments(action_class)
|
205
|
+
action = get_actions.find { |action| action[:class].to_s == action_class.to_s }
|
304
206
|
|
305
|
-
|
306
|
-
|
207
|
+
action[:arguments]
|
208
|
+
end
|
307
209
|
|
308
|
-
|
309
|
-
|
210
|
+
def get_scopes
|
211
|
+
return [] if self.class.scopes_loader.blank?
|
310
212
|
|
311
|
-
self
|
213
|
+
self.class.scopes_loader.bag
|
312
214
|
end
|
313
215
|
|
314
216
|
def default_panel_name
|
@@ -320,63 +222,103 @@ module Avo
|
|
320
222
|
when :edit
|
321
223
|
record_title
|
322
224
|
when :new
|
323
|
-
t("avo.create_new_item", item: name.
|
225
|
+
t("avo.create_new_item", item: name.downcase).upcase_first
|
324
226
|
end
|
325
227
|
end
|
326
228
|
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
229
|
+
def class_name
|
230
|
+
self.class.name.demodulize
|
231
|
+
end
|
232
|
+
|
331
233
|
def model_class
|
332
|
-
|
234
|
+
# get the model class off of the static property
|
235
|
+
return self.class.model_class if self.class.model_class.present?
|
333
236
|
|
334
|
-
|
237
|
+
# get the model class off of the record
|
238
|
+
return @record.base_class if @record.present?
|
239
|
+
|
240
|
+
# generate a model class
|
241
|
+
class_name.safe_constantize
|
335
242
|
end
|
336
243
|
|
337
244
|
def record_title
|
338
245
|
return name if @record.nil?
|
339
246
|
|
340
|
-
|
341
|
-
return
|
247
|
+
the_title = @record.send title
|
248
|
+
return the_title if the_title.present?
|
249
|
+
|
250
|
+
@record.id
|
251
|
+
rescue
|
252
|
+
name
|
253
|
+
end
|
342
254
|
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
255
|
+
def resource_description
|
256
|
+
return instance_exec(&self.class.description) if self.class.description.respond_to? :call
|
257
|
+
|
258
|
+
# Show the description only on the resource index view.
|
259
|
+
# If the user wants to conditionally it on all pages, they should use a block.
|
260
|
+
if view == :index
|
261
|
+
return self.class.description if self.class.description.is_a? String
|
349
262
|
end
|
350
263
|
end
|
351
264
|
|
352
|
-
def
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
265
|
+
def translation_key
|
266
|
+
self.class.translation_key || "avo.resource_translations.#{class_name.underscore}"
|
267
|
+
end
|
268
|
+
|
269
|
+
def name
|
270
|
+
default = class_name.underscore.humanize
|
271
|
+
|
272
|
+
return @name if @name.present?
|
273
|
+
|
274
|
+
if translation_key
|
275
|
+
t(translation_key, count: 1, default: default).capitalize
|
276
|
+
else
|
277
|
+
default
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def singular_name
|
282
|
+
name
|
283
|
+
end
|
284
|
+
|
285
|
+
def plural_name
|
286
|
+
default = name.pluralize
|
287
|
+
|
288
|
+
if translation_key
|
289
|
+
t(translation_key, count: 2, default: default).capitalize
|
290
|
+
else
|
291
|
+
default
|
361
292
|
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def underscore_name
|
296
|
+
return @name if @name.present?
|
297
|
+
|
298
|
+
self.class.name.demodulize.underscore
|
299
|
+
end
|
362
300
|
|
301
|
+
def navigation_label
|
302
|
+
plural_name.humanize
|
303
|
+
end
|
304
|
+
|
305
|
+
def available_view_types
|
363
306
|
view_types = [:table]
|
364
307
|
|
365
|
-
view_types << :grid if
|
366
|
-
view_types << :map if map_view.present?
|
308
|
+
view_types << :grid if get_grid_fields.present?
|
367
309
|
|
368
310
|
view_types
|
369
311
|
end
|
370
312
|
|
371
|
-
def
|
313
|
+
def attached_file_fields
|
372
314
|
get_field_definitions.select do |field|
|
373
315
|
[Avo::Fields::FileField, Avo::Fields::FilesField].include? field.class
|
374
316
|
end
|
375
317
|
end
|
376
318
|
|
377
|
-
|
378
|
-
|
379
|
-
get_field_definitions
|
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
|
380
322
|
.reject do |field|
|
381
323
|
field.computed
|
382
324
|
end
|
@@ -384,9 +326,7 @@ module Avo
|
|
384
326
|
[field.database_id.to_s, field]
|
385
327
|
end
|
386
328
|
.to_h
|
387
|
-
end
|
388
329
|
|
389
|
-
def fill_record(record, params, extra_params: [])
|
390
330
|
# Write the field values
|
391
331
|
params.each do |key, value|
|
392
332
|
field = fields_by_database_id[key]
|
@@ -406,7 +346,7 @@ module Avo
|
|
406
346
|
end
|
407
347
|
|
408
348
|
def authorization(user: nil)
|
409
|
-
current_user = user || Avo::Current.
|
349
|
+
current_user = user || Avo::Current.current_user
|
410
350
|
Avo::Services::AuthorizationService.new(current_user, record || model_class, policy_class: authorization_policy)
|
411
351
|
end
|
412
352
|
|
@@ -443,18 +383,19 @@ module Avo
|
|
443
383
|
!field.computed
|
444
384
|
end
|
445
385
|
.map do |field|
|
386
|
+
id = field.id
|
446
387
|
value = field.value
|
447
388
|
|
448
389
|
if field.type == "belongs_to"
|
390
|
+
id = field.foreign_key.to_sym
|
449
391
|
|
450
392
|
reflection = @record._reflections[@params[:via_relation]]
|
451
393
|
|
452
394
|
if field.polymorphic_as.present? && field.types.map(&:to_s).include?(@params[:via_relation_class])
|
453
395
|
# set the value to the actual record
|
454
|
-
|
455
|
-
value = via_resource.find_record(@params[:via_record_id])
|
396
|
+
value = @params[:via_relation_class].safe_constantize.find(@params[:via_record_id])
|
456
397
|
elsif reflection.present? && reflection.foreign_key.present? && field.id.to_s == @params[:via_relation].to_s
|
457
|
-
resource = Avo.
|
398
|
+
resource = Avo::App.resources.get_resource_by_model_class params[:via_relation_class]
|
458
399
|
record = resource.find_record @params[:via_record_id], params: params
|
459
400
|
id_param = reflection.options[:primary_key] || :id
|
460
401
|
|
@@ -462,18 +403,36 @@ module Avo
|
|
462
403
|
end
|
463
404
|
end
|
464
405
|
|
465
|
-
[
|
406
|
+
[id, value]
|
466
407
|
end
|
467
408
|
.to_h
|
468
|
-
.select do |
|
409
|
+
.select do |id, value|
|
469
410
|
value.present?
|
470
411
|
end
|
471
412
|
|
472
|
-
default_values.each do |
|
473
|
-
|
413
|
+
default_values.each do |id, value|
|
414
|
+
if @record.send(id).nil?
|
415
|
+
@record.send("#{id}=", value)
|
416
|
+
end
|
474
417
|
end
|
475
418
|
end
|
476
419
|
|
420
|
+
def route_key
|
421
|
+
class_name.underscore.pluralize
|
422
|
+
end
|
423
|
+
|
424
|
+
def singular_route_key
|
425
|
+
route_key.singularize
|
426
|
+
end
|
427
|
+
|
428
|
+
# This is used as the model class ID
|
429
|
+
# We use this instead of the route_key to maintain compatibility with uncountable models
|
430
|
+
# With uncountable models route key appends an _index suffix (Fish->fish_index)
|
431
|
+
# Example: User->users, MediaItem->media_items, Fish->fish
|
432
|
+
def model_key
|
433
|
+
model_class.model_name.plural
|
434
|
+
end
|
435
|
+
|
477
436
|
def model_name
|
478
437
|
model_class.model_name
|
479
438
|
end
|
@@ -490,6 +449,18 @@ module Avo
|
|
490
449
|
resources_path(resource: self)
|
491
450
|
end
|
492
451
|
|
452
|
+
def label_field
|
453
|
+
get_field_definitions.find do |field|
|
454
|
+
field.as_label.present?
|
455
|
+
end
|
456
|
+
rescue
|
457
|
+
nil
|
458
|
+
end
|
459
|
+
|
460
|
+
def label
|
461
|
+
label_field&.value || record_title
|
462
|
+
end
|
463
|
+
|
493
464
|
def avatar_field
|
494
465
|
get_field_definitions.find do |field|
|
495
466
|
field.as_avatar.present?
|
@@ -514,6 +485,18 @@ module Avo
|
|
514
485
|
nil
|
515
486
|
end
|
516
487
|
|
488
|
+
def description_field
|
489
|
+
get_field_definitions.find do |field|
|
490
|
+
field.as_description.present?
|
491
|
+
end
|
492
|
+
rescue
|
493
|
+
nil
|
494
|
+
end
|
495
|
+
|
496
|
+
def description
|
497
|
+
description_field&.value
|
498
|
+
end
|
499
|
+
|
517
500
|
def form_scope
|
518
501
|
model_class.base_class.to_s.underscore.downcase
|
519
502
|
end
|
@@ -522,6 +505,12 @@ module Avo
|
|
522
505
|
record.present? && record_id.present?
|
523
506
|
end
|
524
507
|
|
508
|
+
def find_record(id, query: nil, params: nil)
|
509
|
+
query ||= self.class.find_scope
|
510
|
+
|
511
|
+
self.class.find_record_method.call(model_class: query, id: id, params: params)
|
512
|
+
end
|
513
|
+
|
525
514
|
def id_attribute
|
526
515
|
:id
|
527
516
|
end
|
@@ -529,19 +518,5 @@ module Avo
|
|
529
518
|
def record_id
|
530
519
|
record.send(id_attribute)
|
531
520
|
end
|
532
|
-
|
533
|
-
def description_attributes
|
534
|
-
{
|
535
|
-
view: view,
|
536
|
-
resource: self,
|
537
|
-
record: record
|
538
|
-
}
|
539
|
-
end
|
540
|
-
|
541
|
-
private
|
542
|
-
|
543
|
-
def entity_loader(entity)
|
544
|
-
instance_variable_get("@#{entity.to_s.pluralize}_loader")
|
545
|
-
end
|
546
521
|
end
|
547
522
|
end
|
@@ -50,7 +50,7 @@ module Avo
|
|
50
50
|
when Symbol
|
51
51
|
context.send(name)
|
52
52
|
when Proc
|
53
|
-
|
53
|
+
name.call(context)
|
54
54
|
else
|
55
55
|
name.to_s
|
56
56
|
end
|
@@ -61,7 +61,7 @@ module Avo
|
|
61
61
|
when Symbol
|
62
62
|
context.send(path)
|
63
63
|
when Proc
|
64
|
-
|
64
|
+
path.call(context)
|
65
65
|
else
|
66
66
|
context.url_for(path)
|
67
67
|
end
|
@@ -4,17 +4,21 @@ module Avo
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
class_attribute :
|
7
|
+
class_attribute :backup_items_holder
|
8
8
|
end
|
9
9
|
|
10
10
|
class_methods do
|
11
11
|
def with_temporary_items(&block)
|
12
12
|
# back-up the previous items
|
13
|
-
self.
|
13
|
+
self.backup_items_holder = items_holder
|
14
|
+
|
15
|
+
self.items_holder = Avo::Resources::Items::Holder.new
|
16
|
+
|
17
|
+
instance_eval(&block)
|
14
18
|
end
|
15
19
|
|
16
20
|
def restore_items_from_backup
|
17
|
-
self.
|
21
|
+
self.items_holder = backup_items_holder if backup_items_holder.present?
|
18
22
|
end
|
19
23
|
|
20
24
|
def with_new_items(&block)
|