avo 2.12.0 → 2.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of avo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +2 -1
- data/app/components/avo/actions_component.html.erb +3 -3
- data/app/components/avo/actions_component.rb +12 -3
- data/app/components/avo/button_component.rb +1 -3
- data/app/components/avo/fields/common/gravatar_viewer_component.html.erb +1 -1
- data/app/components/avo/fields/date_field/edit_component.html.erb +0 -3
- data/app/components/avo/fields/date_time_field/edit_component.html.erb +0 -2
- data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/tags_field/show_component.rb +0 -2
- data/app/components/avo/item_switcher_component.html.erb +1 -1
- data/app/components/avo/panel_component.html.erb +1 -1
- data/app/components/avo/panel_component.rb +3 -4
- data/app/components/avo/resource_component.rb +6 -4
- data/app/components/avo/sidebar_component.html.erb +1 -1
- data/app/components/avo/tab_group_component.html.erb +1 -1
- data/app/components/avo/tab_switcher_component.rb +2 -2
- data/app/components/avo/views/resource_edit_component.html.erb +1 -1
- data/app/components/avo/views/resource_edit_component.rb +1 -1
- data/app/components/avo/views/resource_index_component.html.erb +3 -3
- data/app/components/avo/views/resource_index_component.rb +18 -1
- data/app/components/avo/views/resource_show_component.html.erb +139 -48
- data/app/components/avo/views/resource_show_component.rb +1 -0
- data/app/controllers/avo/base_controller.rb +87 -33
- data/app/controllers/avo/search_controller.rb +57 -20
- data/app/javascript/js/controllers/menu_controller.js +2 -2
- data/app/javascript/js/controllers/search_controller.js +42 -15
- data/app/views/avo/associations/new.html.erb +1 -0
- data/app/views/avo/dashboards/show.html.erb +1 -1
- data/app/views/avo/debug/index.html.erb +1 -1
- data/app/views/avo/debug/report.html.erb +1 -0
- data/app/views/avo/home/index.html.erb +1 -1
- data/app/views/avo/partials/_resource_search.html.erb +6 -0
- data/app/views/avo/private/design.html.erb +2 -2
- data/app/views/layouts/avo/application.html.erb +1 -1
- data/lib/avo/base_resource.rb +5 -1
- data/lib/avo/concerns/has_editable_controls.rb +34 -0
- data/lib/avo/concerns/has_fields.rb +11 -10
- data/lib/avo/fields/base_field.rb +1 -1
- data/lib/avo/fields/date_field.rb +1 -3
- data/lib/avo/fields/field_extensions/has_include_blank.rb +1 -1
- data/lib/avo/fields/has_base_field.rb +2 -0
- data/lib/avo/fields/key_value_field.rb +6 -6
- data/lib/avo/hosts/base_host.rb +2 -1
- data/lib/avo/hosts/search_scope_host.rb +7 -0
- data/lib/avo/licensing/h_q.rb +12 -4
- data/lib/avo/licensing/pro_license.rb +1 -0
- data/lib/avo/menu/builder.rb +2 -0
- data/lib/avo/resources/controls/action.rb +32 -0
- data/lib/avo/resources/controls/actions_list.rb +19 -0
- data/lib/avo/resources/controls/back_button.rb +13 -0
- data/lib/avo/resources/controls/base_control.rb +59 -0
- data/lib/avo/resources/controls/delete_button.rb +13 -0
- data/lib/avo/resources/controls/detach_button.rb +13 -0
- data/lib/avo/resources/controls/edit_button.rb +13 -0
- data/lib/avo/resources/controls/execution_context.rb +58 -0
- data/lib/avo/resources/controls/items_holder.rb +19 -0
- data/lib/avo/resources/controls/link_to.rb +27 -0
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/action.tt +1 -1
- data/lib/generators/avo/templates/initializer/avo.tt +1 -0
- data/lib/generators/avo/templates/resource/resource.tt +1 -1
- data/lib/generators/avo/templates/resource_tools/partial.tt +1 -1
- data/lib/generators/avo/templates/standalone_action.tt +1 -1
- data/public/avo-assets/avo.css +564 -44
- data/public/avo-assets/avo.js +47 -47
- data/public/avo-assets/avo.js.map +2 -2
- metadata +14 -3
- data/lib/avo/concerns/has_model.rb +0 -11
@@ -115,7 +115,7 @@ module Avo
|
|
115
115
|
add_breadcrumb via_resource.model_title, resource_path(model: via_model, resource: via_resource)
|
116
116
|
end
|
117
117
|
|
118
|
-
add_breadcrumb @resource.plural_name.humanize
|
118
|
+
add_breadcrumb @resource.plural_name.humanize, resources_path(resource: @resource)
|
119
119
|
add_breadcrumb t("avo.new").humanize
|
120
120
|
end
|
121
121
|
|
@@ -129,21 +129,14 @@ module Avo
|
|
129
129
|
@reflection = @model._reflections[params[:via_relation]]
|
130
130
|
# Figure out what kind of association does the record have with the parent record
|
131
131
|
|
132
|
-
# belongs_to
|
133
|
-
# has_many
|
132
|
+
# Fills in the required infor for belongs_to and has_many
|
134
133
|
# Get the foreign key and set it to the id we received in the params
|
135
134
|
if @reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection) || @reflection.is_a?(ActiveRecord::Reflection::HasManyReflection)
|
136
|
-
|
137
|
-
@model.send("#{foreign_key}=", params[:via_resource_id])
|
135
|
+
@model.send("#{@reflection.foreign_key}=", params[:via_resource_id])
|
138
136
|
@model.save
|
139
137
|
end
|
140
138
|
|
141
|
-
# has_one
|
142
|
-
# has_one_through
|
143
|
-
|
144
|
-
# has_many_through
|
145
|
-
# has_and_belongs_to_many
|
146
|
-
# polymorphic
|
139
|
+
# For when working with has_one, has_one_through, has_many_through, has_and_belongs_to_many, polymorphic
|
147
140
|
if @reflection.is_a? ActiveRecord::Reflection::ThroughReflection
|
148
141
|
# find the record
|
149
142
|
via_resource = ::Avo::App.get_resource_by_model_name params[:via_relation_class]
|
@@ -153,13 +146,14 @@ module Avo
|
|
153
146
|
end
|
154
147
|
end
|
155
148
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
149
|
+
add_breadcrumb @resource.plural_name.humanize, resources_path(resource: @resource)
|
150
|
+
add_breadcrumb t("avo.new").humanize
|
151
|
+
set_actions
|
152
|
+
|
153
|
+
if saved
|
154
|
+
create_success_action
|
155
|
+
else
|
156
|
+
create_fail_action
|
163
157
|
end
|
164
158
|
end
|
165
159
|
|
@@ -171,26 +165,20 @@ module Avo
|
|
171
165
|
# model gets instantiated and filled in the fill_model method
|
172
166
|
saved = save_model
|
173
167
|
@resource = @resource.hydrate(model: @model, view: :edit, user: _current_user)
|
168
|
+
set_actions
|
174
169
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
flash.now[:error] = t "avo.you_missed_something_check_form"
|
180
|
-
format.html { render :edit, status: :unprocessable_entity }
|
181
|
-
end
|
170
|
+
if saved
|
171
|
+
update_success_action
|
172
|
+
else
|
173
|
+
update_fail_action
|
182
174
|
end
|
183
175
|
end
|
184
176
|
|
185
177
|
def destroy
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
error_message = @errors.present? ? @errors.first : t("avo.failed")
|
191
|
-
|
192
|
-
format.html { redirect_back fallback_location: params[:referrer] || resources_path(resource: @resource, turbo_frame: params[:turbo_frame], view_type: params[:view_type]), error: error_message }
|
193
|
-
end
|
178
|
+
if destroy_model
|
179
|
+
destroy_success_action
|
180
|
+
else
|
181
|
+
destroy_fail_action
|
194
182
|
end
|
195
183
|
end
|
196
184
|
|
@@ -401,6 +389,27 @@ module Avo
|
|
401
389
|
add_breadcrumb t("avo.edit").humanize
|
402
390
|
end
|
403
391
|
|
392
|
+
def create_success_action
|
393
|
+
respond_to do |format|
|
394
|
+
format.html { redirect_to after_create_path, notice: create_success_message}
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
def create_fail_action
|
399
|
+
respond_to do |format|
|
400
|
+
flash.now[:error] = create_fail_message
|
401
|
+
format.html { render :new, status: :unprocessable_entity }
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def create_success_message
|
406
|
+
"#{@resource.name} #{t("avo.was_successfully_created")}."
|
407
|
+
end
|
408
|
+
|
409
|
+
def create_fail_message
|
410
|
+
t "avo.you_missed_something_check_form"
|
411
|
+
end
|
412
|
+
|
404
413
|
def after_create_path
|
405
414
|
# If this is an associated record return to the association show page
|
406
415
|
if params[:via_relation_class].present? && params[:via_resource_id].present?
|
@@ -412,12 +421,57 @@ module Avo
|
|
412
421
|
redirect_path_from_resource_option(:after_create_path) || resource_path(model: @model, resource: @resource)
|
413
422
|
end
|
414
423
|
|
424
|
+
def update_success_action
|
425
|
+
respond_to do |format|
|
426
|
+
format.html { redirect_to after_update_path, notice: update_success_message }
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
def update_fail_action
|
431
|
+
respond_to do |format|
|
432
|
+
flash.now[:error] = update_fail_message
|
433
|
+
format.html { render :edit, status: :unprocessable_entity }
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
def update_success_message
|
438
|
+
"#{@resource.name} #{t("avo.was_successfully_updated")}."
|
439
|
+
end
|
440
|
+
|
441
|
+
def update_fail_message
|
442
|
+
t "avo.you_missed_something_check_form"
|
443
|
+
end
|
444
|
+
|
415
445
|
def after_update_path
|
416
446
|
return params[:referrer] if params[:referrer].present?
|
417
447
|
|
418
448
|
redirect_path_from_resource_option(:after_update_path) || resource_path(model: @model, resource: @resource)
|
419
449
|
end
|
420
450
|
|
451
|
+
def destroy_success_action
|
452
|
+
respond_to do |format|
|
453
|
+
format.html { redirect_to after_destroy_path, notice: destroy_success_message }
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
def destroy_fail_action
|
458
|
+
respond_to do |format|
|
459
|
+
format.html { redirect_back fallback_location: params[:referrer] || resources_path(resource: @resource, turbo_frame: params[:turbo_frame], view_type: params[:view_type]), error: destroy_fail_message }
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
def destroy_success_message
|
464
|
+
t("avo.resource_destroyed", attachment_class: @attachment_class)
|
465
|
+
end
|
466
|
+
|
467
|
+
def destroy_fail_message
|
468
|
+
@errors.present? ? @errors.first : t("avo.failed")
|
469
|
+
end
|
470
|
+
|
471
|
+
def after_destroy_path
|
472
|
+
params[:referrer] || resources_path(resource: @resource, turbo_frame: params[:turbo_frame], view_type: params[:view_type])
|
473
|
+
end
|
474
|
+
|
421
475
|
def redirect_path_from_resource_option(action = :after_update_path)
|
422
476
|
return nil if @resource.class.send(action).blank?
|
423
477
|
|
@@ -44,10 +44,13 @@ module Avo
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def search_resource(resource)
|
47
|
-
query =
|
47
|
+
query = Avo::Hosts::SearchScopeHost.new(
|
48
|
+
block: resource.search_query,
|
49
|
+
params: params,
|
50
|
+
scope: resource.class.scope.limit(8)
|
51
|
+
).handle
|
48
52
|
|
49
|
-
|
50
|
-
query = apply_attach_scope query
|
53
|
+
query = apply_scope(query) if should_apply_any_scope?
|
51
54
|
|
52
55
|
results = apply_search_metadata(query, resource)
|
53
56
|
|
@@ -67,22 +70,19 @@ module Avo
|
|
67
70
|
[resource.name.pluralize.downcase, result_object]
|
68
71
|
end
|
69
72
|
|
70
|
-
#
|
71
|
-
#
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
# No need to modify the query if there's no attach_scope present.
|
79
|
-
return query if field.attach_scope.blank?
|
80
|
-
|
81
|
-
# Try to fetch the parent.
|
82
|
-
if params[:via_reflection_id].present?
|
83
|
-
parent = params[:via_reflection_class].safe_constantize.find params[:via_reflection_id]
|
73
|
+
# When searching in a `has_many` association and will scope out the records against the parent record.
|
74
|
+
# This is also used when looking for `belongs_to` associations, and this method applies the parents `attach_scope` if present.
|
75
|
+
def apply_scope(query)
|
76
|
+
if should_apply_has_many_scope?
|
77
|
+
apply_has_many_scope
|
78
|
+
elsif should_apply_attach_scope?
|
79
|
+
apply_attach_scope(query, parent)
|
84
80
|
end
|
81
|
+
end
|
85
82
|
|
83
|
+
# Parent passed as argument to be used as a variable instead of the method "def parent"
|
84
|
+
# Otherwise parent = params...safe_constantize... will try to call method "def parent="
|
85
|
+
def apply_attach_scope(query, parent)
|
86
86
|
# If the parent is nil it probably means that someone's creating the record so it's not attached yet.
|
87
87
|
# In these scenarios, try to find the grandparent for the new views where the parent is nil
|
88
88
|
# and initialize the parent record with the grandparent attached so the user has the required information
|
@@ -94,8 +94,13 @@ module Avo
|
|
94
94
|
)
|
95
95
|
end
|
96
96
|
|
97
|
-
|
98
|
-
|
97
|
+
Avo::Hosts::AssociationScopeHost.new(block: attach_scope, query: query, parent: parent).handle
|
98
|
+
end
|
99
|
+
|
100
|
+
def apply_has_many_scope
|
101
|
+
scope = parent.send(params[:via_association_id])
|
102
|
+
|
103
|
+
Avo::Hosts::SearchScopeHost.new(block: @resource.search_query, params: params, scope: scope).handle
|
99
104
|
end
|
100
105
|
|
101
106
|
def apply_search_metadata(models, avo_resource)
|
@@ -118,9 +123,41 @@ module Avo
|
|
118
123
|
end
|
119
124
|
end
|
120
125
|
|
121
|
-
|
126
|
+
private
|
127
|
+
|
128
|
+
def should_apply_has_many_scope?
|
129
|
+
params[:via_association] == "has_many" && @resource.search_query.present?
|
130
|
+
end
|
131
|
+
|
132
|
+
def should_apply_attach_scope?
|
133
|
+
params[:via_association] == "belongs_to" && attach_scope.present?
|
134
|
+
end
|
135
|
+
|
136
|
+
def should_apply_any_scope?
|
137
|
+
should_apply_has_many_scope? || should_apply_attach_scope?
|
138
|
+
end
|
139
|
+
|
140
|
+
def attach_scope
|
141
|
+
@attach_scope ||= field&.attach_scope
|
142
|
+
end
|
143
|
+
|
144
|
+
def field
|
145
|
+
@field ||= fetch_field
|
146
|
+
end
|
147
|
+
|
148
|
+
def parent
|
149
|
+
@parent ||= fetch_parent
|
150
|
+
end
|
151
|
+
|
152
|
+
def fetch_field
|
122
153
|
fields = ::Avo::App.get_resource_by_model_name(params[:via_reflection_class]).get_field_definitions
|
123
154
|
fields.find { |f| f.id.to_s == params[:via_association_id] }
|
124
155
|
end
|
156
|
+
|
157
|
+
def fetch_parent
|
158
|
+
return unless params[:via_reflection_id].present?
|
159
|
+
|
160
|
+
params[:via_reflection_class].safe_constantize.find params[:via_reflection_id]
|
161
|
+
end
|
125
162
|
end
|
126
163
|
end
|
@@ -22,8 +22,8 @@ export default class extends Controller {
|
|
22
22
|
}
|
23
23
|
|
24
24
|
get initiallyCollapsed() {
|
25
|
-
if (this.
|
26
|
-
return this.
|
25
|
+
if (!this.userState) {
|
26
|
+
return this.defaultState === 'collapsed'
|
27
27
|
}
|
28
28
|
|
29
29
|
return this.userState === 'collapsed'
|
@@ -48,6 +48,10 @@ export default class extends Controller {
|
|
48
48
|
return this.dataset.viaAssociation === 'belongs_to'
|
49
49
|
}
|
50
50
|
|
51
|
+
get isHasManySearch() {
|
52
|
+
return this.dataset.viaAssociation === 'has_many'
|
53
|
+
}
|
54
|
+
|
51
55
|
get isGlobalSearch() {
|
52
56
|
return this.dataset.searchResource === 'global'
|
53
57
|
}
|
@@ -83,27 +87,50 @@ export default class extends Controller {
|
|
83
87
|
params.global = true
|
84
88
|
}
|
85
89
|
|
86
|
-
if (this.isBelongsToSearch) {
|
87
|
-
params =
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
via_relation: this.dataset.viaRelation,
|
90
|
+
if (this.isBelongsToSearch || this.isHasManySearch) {
|
91
|
+
params = this.addAssociationParams(params)
|
92
|
+
params = this.addReflectionParams(params)
|
93
|
+
|
94
|
+
if (this.isBelongsToSearch) {
|
95
|
+
params = {
|
96
|
+
...params,
|
97
|
+
// eslint-disable-next-line camelcase
|
98
|
+
via_parent_resource_id: this.dataset.viaParentResourceId,
|
99
|
+
// eslint-disable-next-line camelcase
|
100
|
+
via_parent_resource_class: this.dataset.viaParentResourceClass,
|
101
|
+
// eslint-disable-next-line camelcase
|
102
|
+
via_relation: this.dataset.viaRelation,
|
103
|
+
}
|
101
104
|
}
|
102
105
|
}
|
103
106
|
|
104
107
|
return params
|
105
108
|
}
|
106
109
|
|
110
|
+
addAssociationParams(params) {
|
111
|
+
params = {
|
112
|
+
...params,
|
113
|
+
// eslint-disable-next-line camelcase
|
114
|
+
via_association: this.dataset.viaAssociation,
|
115
|
+
// eslint-disable-next-line camelcase
|
116
|
+
via_association_id: this.dataset.viaAssociationId,
|
117
|
+
}
|
118
|
+
|
119
|
+
return params
|
120
|
+
}
|
121
|
+
|
122
|
+
addReflectionParams(params) {
|
123
|
+
params = {
|
124
|
+
...params,
|
125
|
+
// eslint-disable-next-line camelcase
|
126
|
+
via_reflection_class: this.dataset.viaReflectionClass,
|
127
|
+
// eslint-disable-next-line camelcase
|
128
|
+
via_reflection_id: this.dataset.viaReflectionId,
|
129
|
+
}
|
130
|
+
|
131
|
+
return params
|
132
|
+
}
|
133
|
+
|
107
134
|
handleOnSelect({ item }) {
|
108
135
|
if (this.isBelongsToSearch) {
|
109
136
|
this.updateFieldAttribute(this.hiddenIdTarget, 'value', item._id)
|
@@ -13,6 +13,7 @@
|
|
13
13
|
<div class="flex-1 flex items-center justify-center px-0 lg:px-8 text-lg mt-8 mb-12">
|
14
14
|
<% if @field.searchable %>
|
15
15
|
<%= render Avo::Fields::BelongsToField::AutocompleteComponent.new form: form,
|
16
|
+
classes: input_classes("w-full"),
|
16
17
|
field: @field,
|
17
18
|
model_key: @field.target_resource&.model_key,
|
18
19
|
foreign_key: 'related_id',
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= render Avo::PanelComponent.new(
|
1
|
+
<%= render Avo::PanelComponent.new(name: @dashboard.name, description: @dashboard.description) do |c| %>
|
2
2
|
<% c.bare_content do %>
|
3
3
|
<% if @dashboard.items.present? %>
|
4
4
|
<div class="min-h-24">
|
@@ -14,7 +14,7 @@
|
|
14
14
|
hq_payload = Avo::Licensing::HQ.new(request).payload
|
15
15
|
%>
|
16
16
|
<div class="flex flex-col">
|
17
|
-
<%= render Avo::PanelComponent.new(
|
17
|
+
<%= render Avo::PanelComponent.new(name: 'Debug Avo', description: 'Use this page to debug the Avo license.') do |c| %>
|
18
18
|
<% c.tools do %>
|
19
19
|
<% end %>
|
20
20
|
<% c.bare_content do %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div class="flex flex-col">
|
2
|
-
<%= render Avo::PanelComponent.new(
|
2
|
+
<%= render Avo::PanelComponent.new(name: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
|
3
3
|
<% c.body do %>
|
4
4
|
<div class="flex flex-col justify-between py-6 min-h-24">
|
5
5
|
<div class="px-6 space-y-4">
|
@@ -3,6 +3,12 @@
|
|
3
3
|
data-search-target="autocomplete"
|
4
4
|
data-search-resource="<%= resource %>"
|
5
5
|
data-translation-keys='{"no_item_found": "<%= I18n.translate 'avo.no_item_found' %>"}'
|
6
|
+
<% if via_reflection.present? %>
|
7
|
+
data-via-association="<%= via_reflection[:association] %>"
|
8
|
+
data-via-association-id="<%= via_reflection[:association_id] %>"
|
9
|
+
data-via-reflection-class="<%= via_reflection[:class] %>"
|
10
|
+
data-via-reflection-id="<%= via_reflection[:id] %>"
|
11
|
+
<% end %>
|
6
12
|
>
|
7
13
|
</div>
|
8
14
|
<div class="hidden relative inline-flex text-gray-400 text-sm border border-gray-300 rounded cursor-pointer" data-search-target="button"></div>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<div class="flex flex-col">
|
2
|
-
<%= render Avo::PanelComponent.new(
|
2
|
+
<%= render Avo::PanelComponent.new(name: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
|
3
3
|
<% c.tools do %>
|
4
|
-
<%= a_link('/admin', icon: 'arrow-left', style: :primary, is_link: true) do %>
|
4
|
+
<%= a_link('/admin', icon: 'arrow-left', color: :green, style: :primary, is_link: true) do %>
|
5
5
|
Primary
|
6
6
|
<% end %>
|
7
7
|
|
@@ -18,7 +18,7 @@
|
|
18
18
|
<% end %>
|
19
19
|
<% end %>
|
20
20
|
</head>
|
21
|
-
<body class="bg-
|
21
|
+
<body class="bg-application os-mac">
|
22
22
|
<div class="relative flex flex-1 w-full min-h-full" data-controller="sidebar" data-sidebar-open-value="<%= @sidebar_open %>">
|
23
23
|
<div class="flex-1 flex flex-col max-w-full">
|
24
24
|
<%= render partial: "avo/partials/navbar" %>
|
data/lib/avo/base_resource.rb
CHANGED
@@ -3,8 +3,8 @@ module Avo
|
|
3
3
|
extend ActiveSupport::DescendantsTracker
|
4
4
|
|
5
5
|
include ActionView::Helpers::UrlHelper
|
6
|
-
include Avo::Concerns::HasModel
|
7
6
|
include Avo::Concerns::HasFields
|
7
|
+
include Avo::Concerns::HasEditableControls
|
8
8
|
include Avo::Concerns::HasStimulusControllers
|
9
9
|
include Avo::Concerns::ModelClassConstantized
|
10
10
|
|
@@ -439,5 +439,9 @@ module Avo
|
|
439
439
|
def ordering_host(**args)
|
440
440
|
Avo::Hosts::Ordering.new resource: self, options: self.class.ordering, **args
|
441
441
|
end
|
442
|
+
|
443
|
+
def has_model_id?
|
444
|
+
model.present? && model.id.present?
|
445
|
+
end
|
442
446
|
end
|
443
447
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Avo
|
2
|
+
module Concerns
|
3
|
+
module HasEditableControls
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
class_attribute :show_controls
|
8
|
+
class_attribute :show_controls_holder
|
9
|
+
class_attribute :show_controls_holder_called, default: false
|
10
|
+
end
|
11
|
+
|
12
|
+
def has_show_controls?
|
13
|
+
return false if ::Avo::App.license.lacks_with_trial(:resource_show_controls)
|
14
|
+
|
15
|
+
self.class.show_controls.present?
|
16
|
+
end
|
17
|
+
|
18
|
+
def render_show_controls
|
19
|
+
return [] if ::Avo::App.license.lacks_with_trial(:resource_show_controls)
|
20
|
+
|
21
|
+
if show_controls.present?
|
22
|
+
Avo::Resources::Controls::ExecutionContext.new(
|
23
|
+
block: show_controls,
|
24
|
+
resource: self,
|
25
|
+
record: model,
|
26
|
+
view: view
|
27
|
+
).handle&.items || []
|
28
|
+
else
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -17,19 +17,19 @@ module Avo
|
|
17
17
|
def field(name, **args, &block)
|
18
18
|
ensure_items_holder_initialized
|
19
19
|
|
20
|
-
|
20
|
+
items_holder.field name, **args, &block
|
21
21
|
end
|
22
22
|
|
23
23
|
def panel(name = nil, **args, &block)
|
24
24
|
ensure_items_holder_initialized
|
25
25
|
|
26
|
-
|
26
|
+
items_holder.panel name, **args, &block
|
27
27
|
end
|
28
28
|
|
29
29
|
def tabs(&block)
|
30
30
|
ensure_items_holder_initialized
|
31
31
|
|
32
|
-
|
32
|
+
items_holder.tabs Avo::TabGroupBuilder.parse_block(&block)
|
33
33
|
end
|
34
34
|
|
35
35
|
def tool(klass, **args)
|
@@ -39,27 +39,29 @@ module Avo
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def heading(body, **args)
|
42
|
-
|
42
|
+
ensure_items_holder_initialized
|
43
|
+
|
44
|
+
items_holder.heading body, **args
|
43
45
|
end
|
44
46
|
# END DSL methods
|
45
47
|
|
46
48
|
def items
|
47
|
-
if
|
48
|
-
|
49
|
+
if items_holder.present?
|
50
|
+
items_holder.items
|
49
51
|
else
|
50
52
|
[]
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
54
56
|
def tools
|
55
|
-
|
57
|
+
tools_holder
|
56
58
|
end
|
57
59
|
|
58
60
|
# Dives deep into panels and tabs to fetch all the fields for a resource.
|
59
61
|
def fields(only_root: false)
|
60
62
|
fields = []
|
61
63
|
|
62
|
-
|
64
|
+
items.each do |item|
|
63
65
|
next if item.nil?
|
64
66
|
|
65
67
|
unless only_root
|
@@ -76,7 +78,6 @@ module Avo
|
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
79
|
-
|
80
81
|
if item.is_field?
|
81
82
|
fields << item
|
82
83
|
end
|
@@ -86,7 +87,7 @@ module Avo
|
|
86
87
|
end
|
87
88
|
|
88
89
|
def tab_groups
|
89
|
-
|
90
|
+
items.select do |item|
|
90
91
|
item.instance_of? Avo::TabGroup
|
91
92
|
end
|
92
93
|
end
|
@@ -160,7 +160,7 @@ module Avo
|
|
160
160
|
final_value = @model.send(property) if (model_or_class(@model) == "model") && @model.respond_to?(property)
|
161
161
|
|
162
162
|
# On new views and actions modals we need to prefill the fields
|
163
|
-
if
|
163
|
+
if @view.in?([:new, :create]) || @action.present?
|
164
164
|
if default.present?
|
165
165
|
final_value = if default.respond_to?(:call)
|
166
166
|
default.call
|
@@ -5,15 +5,13 @@ module Avo
|
|
5
5
|
attr_reader :picker_format
|
6
6
|
attr_reader :disable_mobile
|
7
7
|
attr_reader :format
|
8
|
-
attr_reader :relative
|
9
8
|
|
10
9
|
def initialize(id, **args, &block)
|
11
10
|
super(id, **args, &block)
|
12
11
|
|
13
|
-
add_string_prop args, :first_day_of_week,
|
12
|
+
add_string_prop args, :first_day_of_week, 1
|
14
13
|
add_string_prop args, :picker_format, "Y-m-d"
|
15
14
|
add_string_prop args, :format, "yyyy-LL-dd"
|
16
|
-
add_boolean_prop args, :relative
|
17
15
|
add_boolean_prop args, :disable_mobile
|
18
16
|
end
|
19
17
|
|
@@ -6,6 +6,7 @@ module Avo
|
|
6
6
|
attr_accessor :attach_scope
|
7
7
|
attr_accessor :description
|
8
8
|
attr_accessor :discreet_pagination
|
9
|
+
attr_accessor :hide_search_input
|
9
10
|
|
10
11
|
def initialize(id, **args, &block)
|
11
12
|
super(id, **args, &block)
|
@@ -14,6 +15,7 @@ module Avo
|
|
14
15
|
@attach_scope = args[:attach_scope].present? ? args[:attach_scope] : nil
|
15
16
|
@display = args[:display].present? ? args[:display] : :show
|
16
17
|
@searchable = args[:searchable] == true
|
18
|
+
@hide_search_input = args[:hide_search_input] || false
|
17
19
|
@description = args[:description]
|
18
20
|
@use_resource = args[:use_resource] || nil
|
19
21
|
@discreet_pagination = args[:discreet_pagination] || false
|