avo 2.11.3.pre.3 → 2.13.0
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.lock +2 -4
- 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/card_component.html.erb +8 -8
- 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/index/ordering/buttons_component.html.erb +1 -1
- data/app/components/avo/index/resource_controls_component.rb +1 -1
- 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/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 -21
- data/app/components/avo/views/resource_index_component.html.erb +49 -97
- data/app/components/avo/views/resource_index_component.rb +19 -0
- data/app/components/avo/views/resource_show_component.html.erb +139 -53
- data/app/components/avo/views/resource_show_component.rb +1 -0
- data/app/controllers/avo/application_controller.rb +7 -3
- data/app/controllers/avo/associations_controller.rb +2 -2
- data/app/controllers/avo/base_controller.rb +11 -18
- data/app/controllers/avo/cards_controller.rb +5 -18
- data/app/controllers/avo/dashboards_controller.rb +2 -4
- data/app/controllers/avo/search_controller.rb +57 -20
- data/app/javascript/js/controllers/{card_controller.js → dashboard_card_controller.js} +0 -0
- data/app/javascript/js/controllers/menu_controller.js +2 -2
- data/app/javascript/js/controllers/search_controller.js +42 -15
- data/app/javascript/js/controllers.js +2 -2
- data/app/views/avo/associations/new.html.erb +1 -0
- data/app/views/avo/cards/_metric_card.html.erb +2 -2
- data/app/views/avo/dashboards/show.html.erb +20 -3
- 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/config/routes.rb +0 -3
- data/lib/avo/base_card.rb +21 -40
- data/lib/avo/base_resource.rb +5 -2
- data/lib/avo/concerns/has_editable_controls.rb +34 -0
- data/lib/avo/concerns/has_fields.rb +11 -10
- data/lib/avo/dashboards/base_dashboard.rb +50 -15
- data/lib/avo/dashboards/base_divider.rb +1 -5
- data/lib/avo/dashboards/chartkick_card.rb +4 -5
- data/lib/avo/fields/base_field.rb +13 -7
- 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/field_extensions/visible_in_different_views.rb +1 -12
- data/lib/avo/fields/has_base_field.rb +18 -1
- data/lib/avo/fields/key_value_field.rb +6 -6
- data/lib/avo/hosts/base_host.rb +2 -1
- data/lib/avo/hosts/dashboard_card.rb +1 -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/tab.rb +1 -3
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/action.tt +1 -1
- data/lib/generators/avo/templates/cards/partial_card_partial.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 +592 -124
- data/public/avo-assets/avo.js +48 -48
- data/public/avo-assets/avo.js.map +3 -3
- metadata +17 -10
- data/app/components/avo/cards_list_component.html.erb +0 -16
- data/app/components/avo/cards_list_component.rb +0 -13
- data/lib/avo/concerns/has_cards.rb +0 -88
- data/lib/avo/concerns/has_model.rb +0 -11
- data/lib/avo/concerns/styles_cards.rb +0 -48
@@ -5,65 +5,151 @@
|
|
5
5
|
selected_resources: [@resource.model.id],
|
6
6
|
**@resource.stimulus_data_attributes
|
7
7
|
} do %>
|
8
|
-
|
9
|
-
<%= content_tag :div, class: "mb-6" do %>
|
10
|
-
<%= render Avo::CardsListComponent.new parent: @resource %>
|
11
|
-
<% end %>
|
12
|
-
<% end %>
|
13
|
-
<%= render Avo::PanelComponent.new(title: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
|
8
|
+
<%= render Avo::PanelComponent.new(name: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
|
14
9
|
<% c.tools do %>
|
15
|
-
<% if @
|
16
|
-
<%
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
10
|
+
<% if @resource.has_show_controls? %>
|
11
|
+
<% @resource.render_show_controls.each do |control| %>
|
12
|
+
<% if control.back_button? %>
|
13
|
+
<%= a_link back_path,
|
14
|
+
style: :text,
|
15
|
+
title: control.title,
|
16
|
+
data: {
|
17
|
+
tippy: control.title ? :tooltip : nil,
|
18
|
+
},
|
19
|
+
icon: 'arrow-left' do %>
|
20
|
+
<%= control.label %>
|
21
|
+
<% end %>
|
22
|
+
<% elsif control.delete_button? %>
|
23
|
+
<% if can_see_the_destroy_button? %>
|
24
|
+
<%= a_button url: helpers.resource_path(model: @resource.model, resource: @resource),
|
25
|
+
method: :delete,
|
26
|
+
local: true,
|
27
|
+
style: :text,
|
28
|
+
loading: true,
|
29
|
+
confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
|
30
|
+
color: :red,
|
31
|
+
icon: 'trash',
|
32
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
33
|
+
title: control.title,
|
34
|
+
data: {
|
35
|
+
control: :destroy,
|
36
|
+
tippy: control.title ? :tooltip : nil,
|
37
|
+
'resource-id': @resource.model.id,
|
38
|
+
} do %>
|
39
|
+
<%= control.label %>
|
40
|
+
<% end %>
|
41
|
+
<% end %>
|
42
|
+
<% elsif control.actions_list? %>
|
43
|
+
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view, exclude: control.exclude, style: control.style, color: control.color %>
|
44
|
+
<% elsif control.edit_button? %>
|
45
|
+
<% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
|
46
|
+
<% end %>
|
47
|
+
<%= a_link edit_path,
|
48
|
+
color: :primary,
|
49
|
+
style: :primary,
|
50
|
+
title: control.title,
|
51
|
+
data: {
|
52
|
+
tippy: control.title ? :tooltip : nil,
|
53
|
+
},
|
54
|
+
icon: 'edit' do %>
|
55
|
+
<%= control.label %>
|
56
|
+
<% end %>
|
57
|
+
<% elsif control.action? %>
|
58
|
+
<%= a_link control.path,
|
59
|
+
color: control.color,
|
60
|
+
style: control.style,
|
61
|
+
icon: control.icon,
|
62
|
+
title: control.title,
|
63
|
+
data: {
|
64
|
+
tippy: control.title ? :tooltip : nil,
|
65
|
+
'turbo-frame': 'actions_show',
|
66
|
+
'action': 'click->actions-picker#visitAction',
|
67
|
+
} do %>
|
68
|
+
<%= control.label %>
|
69
|
+
<% end %>
|
70
|
+
<% elsif control.link_to? %>
|
71
|
+
<%= a_link control.path,
|
72
|
+
color: control.color,
|
73
|
+
style: control.style,
|
74
|
+
icon: control.icon,
|
75
|
+
title: control.title,
|
76
|
+
target: control.target,
|
77
|
+
class: control.class,
|
78
|
+
data: {
|
79
|
+
**control.data,
|
80
|
+
tippy: control.title ? :tooltip : nil,
|
81
|
+
} do %>
|
82
|
+
<%= control.label %>
|
83
|
+
<% end %>
|
84
|
+
<% elsif control.detach_button? %>
|
85
|
+
<% if @reflection.present? && @resource.model.present? && can_detach? %>
|
86
|
+
<%= a_button url: detach_path,
|
87
|
+
icon: 'detach',
|
88
|
+
method: :delete,
|
89
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
90
|
+
style: :text,
|
91
|
+
data: {
|
92
|
+
confirm: "Are you sure you want to detach this #{title}."
|
93
|
+
} do %>
|
94
|
+
<%= control.label %>
|
95
|
+
<% end %>
|
96
|
+
<% end %>
|
35
97
|
<% end %>
|
36
98
|
<% end %>
|
37
99
|
<% else %>
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
100
|
+
<% if @reflection.present? && @resource.model.present? %>
|
101
|
+
<% if can_detach? %>
|
102
|
+
<%= a_button url: detach_path,
|
103
|
+
icon: 'detach',
|
104
|
+
method: :delete,
|
105
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
106
|
+
style: :text,
|
107
|
+
data: {
|
108
|
+
confirm: "Are you sure you want to detach this #{title}."
|
109
|
+
} do %>
|
110
|
+
<%= t('avo.detach_item', item: title).capitalize %>
|
111
|
+
<% end %>
|
112
|
+
<% end %>
|
113
|
+
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
|
114
|
+
<% if can_see_the_edit_button? %>
|
115
|
+
<%= a_link edit_path,
|
116
|
+
color: :primary,
|
117
|
+
style: :primary,
|
118
|
+
icon: 'edit' do %>
|
119
|
+
<%= t('avo.edit').capitalize %>
|
120
|
+
<% end %>
|
121
|
+
<% end %>
|
122
|
+
<% else %>
|
123
|
+
<%= a_link back_path,
|
47
124
|
style: :text,
|
48
|
-
|
49
|
-
|
50
|
-
color: :red,
|
51
|
-
icon: 'trash',
|
52
|
-
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
53
|
-
data: {
|
54
|
-
control: :destroy,
|
55
|
-
'resource-id': @resource.model.id,
|
56
|
-
} do %>
|
57
|
-
<%= t('avo.delete').capitalize %>
|
125
|
+
icon: 'arrow-left' do %>
|
126
|
+
<%= t('avo.go_back') %>
|
58
127
|
<% end %>
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
128
|
+
<% if can_see_the_destroy_button? %>
|
129
|
+
<%= a_button url: helpers.resource_path(model: @resource.model, resource: @resource),
|
130
|
+
method: :delete,
|
131
|
+
local: true,
|
132
|
+
style: :text,
|
133
|
+
loading: true,
|
134
|
+
confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
|
135
|
+
color: :red,
|
136
|
+
icon: 'trash',
|
137
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
138
|
+
data: {
|
139
|
+
control: :destroy,
|
140
|
+
'resource-id': @resource.model.id,
|
141
|
+
} do %>
|
142
|
+
<%= t('avo.delete').capitalize %>
|
143
|
+
<% end %>
|
144
|
+
<% end %>
|
145
|
+
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
|
146
|
+
<% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
|
147
|
+
<%= a_link edit_path,
|
148
|
+
color: :primary,
|
149
|
+
style: :primary,
|
150
|
+
icon: 'edit' do %>
|
151
|
+
<%= t('avo.edit').capitalize %>
|
152
|
+
<% end %>
|
67
153
|
<% end %>
|
68
154
|
<% end %>
|
69
155
|
<% end %>
|
@@ -118,7 +118,7 @@ module Avo
|
|
118
118
|
def set_resource
|
119
119
|
raise ActionController::RoutingError.new "No route matches" if resource.nil?
|
120
120
|
|
121
|
-
@resource = resource
|
121
|
+
@resource = resource.hydrate(params: params)
|
122
122
|
end
|
123
123
|
|
124
124
|
def set_related_resource
|
@@ -126,7 +126,6 @@ module Avo
|
|
126
126
|
end
|
127
127
|
|
128
128
|
def set_model
|
129
|
-
puts ["controller_name->", controller_name].inspect
|
130
129
|
@model = eager_load_files(@resource, @resource.class.find_scope).find params[:id]
|
131
130
|
end
|
132
131
|
|
@@ -157,7 +156,7 @@ module Avo
|
|
157
156
|
end
|
158
157
|
|
159
158
|
def hydrate_resource
|
160
|
-
@resource.hydrate(view: action_name.to_sym, user: _current_user
|
159
|
+
@resource.hydrate(view: action_name.to_sym, user: _current_user)
|
161
160
|
end
|
162
161
|
|
163
162
|
def hydrate_related_resource
|
@@ -208,6 +207,11 @@ module Avo
|
|
208
207
|
end
|
209
208
|
|
210
209
|
def related_resource
|
210
|
+
# Find the field from the parent resource
|
211
|
+
field = @resource.get_field params[:related_name]
|
212
|
+
|
213
|
+
return field.use_resource if field&.use_resource.present?
|
214
|
+
|
211
215
|
reflection = @model._reflections[params[:related_name]]
|
212
216
|
|
213
217
|
reflected_model = reflection.klass
|
@@ -6,8 +6,8 @@ module Avo
|
|
6
6
|
before_action :set_related_resource_name
|
7
7
|
before_action :set_related_resource, only: [:show, :index, :new, :create, :destroy, :order]
|
8
8
|
before_action :set_reflection_field
|
9
|
-
before_action :set_related_model, only: [:show, :order]
|
10
9
|
before_action :hydrate_related_resource, only: [:show, :index, :create, :destroy, :order]
|
10
|
+
before_action :set_related_model, only: [:show, :order]
|
11
11
|
before_action :set_reflection
|
12
12
|
before_action :set_attachment_class, only: [:show, :index, :new, :create, :destroy, :order]
|
13
13
|
before_action :set_attachment_resource, only: [:show, :index, :new, :create, :destroy, :order]
|
@@ -102,7 +102,7 @@ module Avo
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def set_attachment_resource
|
105
|
-
@attachment_resource = App.get_resource_by_model_name @attachment_class
|
105
|
+
@attachment_resource = @field.use_resource || (App.get_resource_by_model_name @attachment_class)
|
106
106
|
end
|
107
107
|
|
108
108
|
def set_attachment_model
|
@@ -7,7 +7,6 @@ module Avo
|
|
7
7
|
before_action :hydrate_resource
|
8
8
|
before_action :set_applied_filters, only: :index
|
9
9
|
before_action :set_model, only: [:show, :edit, :destroy, :update, :order]
|
10
|
-
before_action :hydrate_resource
|
11
10
|
before_action :set_model_to_fill
|
12
11
|
before_action :set_edit_title_and_breadcrumbs, only: [:edit, :update]
|
13
12
|
before_action :fill_model, only: [:create, :update]
|
@@ -101,7 +100,7 @@ module Avo
|
|
101
100
|
|
102
101
|
def new
|
103
102
|
@model = @resource.model_class.new
|
104
|
-
@resource = @resource.hydrate(model: @model, view: :new)
|
103
|
+
@resource = @resource.hydrate(model: @model, view: :new, user: _current_user)
|
105
104
|
|
106
105
|
set_actions
|
107
106
|
|
@@ -116,7 +115,7 @@ module Avo
|
|
116
115
|
add_breadcrumb via_resource.model_title, resource_path(model: via_model, resource: via_resource)
|
117
116
|
end
|
118
117
|
|
119
|
-
add_breadcrumb @resource.plural_name.humanize
|
118
|
+
add_breadcrumb @resource.plural_name.humanize, resources_path(resource: @resource)
|
120
119
|
add_breadcrumb t("avo.new").humanize
|
121
120
|
end
|
122
121
|
|
@@ -130,21 +129,14 @@ module Avo
|
|
130
129
|
@reflection = @model._reflections[params[:via_relation]]
|
131
130
|
# Figure out what kind of association does the record have with the parent record
|
132
131
|
|
133
|
-
# belongs_to
|
134
|
-
# has_many
|
132
|
+
# Fills in the required infor for belongs_to and has_many
|
135
133
|
# Get the foreign key and set it to the id we received in the params
|
136
134
|
if @reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection) || @reflection.is_a?(ActiveRecord::Reflection::HasManyReflection)
|
137
|
-
|
138
|
-
@model.send("#{foreign_key}=", params[:via_resource_id])
|
135
|
+
@model.send("#{@reflection.foreign_key}=", params[:via_resource_id])
|
139
136
|
@model.save
|
140
137
|
end
|
141
138
|
|
142
|
-
# has_one
|
143
|
-
# has_one_through
|
144
|
-
|
145
|
-
# has_many_through
|
146
|
-
# has_and_belongs_to_many
|
147
|
-
# polymorphic
|
139
|
+
# For when working with has_one, has_one_through, has_many_through, has_and_belongs_to_many, polymorphic
|
148
140
|
if @reflection.is_a? ActiveRecord::Reflection::ThroughReflection
|
149
141
|
# find the record
|
150
142
|
via_resource = ::Avo::App.get_resource_by_model_name params[:via_relation_class]
|
@@ -158,6 +150,9 @@ module Avo
|
|
158
150
|
if saved
|
159
151
|
format.html { redirect_to after_create_path, notice: "#{@resource.name} #{t("avo.was_successfully_created")}." }
|
160
152
|
else
|
153
|
+
add_breadcrumb @resource.plural_name.humanize, resources_path(resource: @resource)
|
154
|
+
add_breadcrumb t("avo.new").humanize
|
155
|
+
set_actions
|
161
156
|
flash.now[:error] = t "avo.you_missed_something_check_form"
|
162
157
|
format.html { render :new, status: :unprocessable_entity }
|
163
158
|
end
|
@@ -171,12 +166,13 @@ module Avo
|
|
171
166
|
def update
|
172
167
|
# model gets instantiated and filled in the fill_model method
|
173
168
|
saved = save_model
|
174
|
-
@resource = @resource.hydrate(model: @model, view: :edit)
|
169
|
+
@resource = @resource.hydrate(model: @model, view: :edit, user: _current_user)
|
175
170
|
|
176
171
|
respond_to do |format|
|
177
172
|
if saved
|
178
173
|
format.html { redirect_to after_update_path, notice: "#{@resource.name} #{t("avo.was_successfully_updated")}." }
|
179
174
|
else
|
175
|
+
set_actions
|
180
176
|
flash.now[:error] = t "avo.you_missed_something_check_form"
|
181
177
|
format.html { render :edit, status: :unprocessable_entity }
|
182
178
|
end
|
@@ -210,9 +206,6 @@ module Avo
|
|
210
206
|
end
|
211
207
|
end
|
212
208
|
|
213
|
-
def cards
|
214
|
-
end
|
215
|
-
|
216
209
|
private
|
217
210
|
|
218
211
|
def save_model
|
@@ -380,7 +373,7 @@ module Avo
|
|
380
373
|
end
|
381
374
|
|
382
375
|
def set_edit_title_and_breadcrumbs
|
383
|
-
@resource = @resource.hydrate(model: @model, view: :edit)
|
376
|
+
@resource = @resource.hydrate(model: @model, view: :edit, user: _current_user)
|
384
377
|
@page_title = @resource.default_panel_name.to_s
|
385
378
|
|
386
379
|
last_crumb_args = {}
|
@@ -2,12 +2,7 @@ require_dependency "avo/application_controller"
|
|
2
2
|
|
3
3
|
module Avo
|
4
4
|
class CardsController < ApplicationController
|
5
|
-
before_action :set_dashboard
|
6
|
-
before_action :set_resource_name
|
7
|
-
before_action :set_resource, if: -> { @dashboard.blank? }
|
8
|
-
before_action :set_model, only: :show, if: -> { @resource.present? }
|
9
|
-
before_action :hydrate_resource, if: -> { @resource.present? }
|
10
|
-
before_action :set_parent, only: :show
|
5
|
+
before_action :set_dashboard, only: :show
|
11
6
|
before_action :set_card, only: :show
|
12
7
|
|
13
8
|
def show
|
@@ -15,23 +10,15 @@ module Avo
|
|
15
10
|
|
16
11
|
private
|
17
12
|
|
18
|
-
def set_parent
|
19
|
-
@parent = @dashboard || @resource
|
20
|
-
end
|
21
|
-
|
22
13
|
def set_dashboard
|
23
|
-
|
24
|
-
|
25
|
-
@dashboard_class = Avo::App.get_dashboard_by_id params[:dashboard_id]
|
26
|
-
|
27
|
-
raise ActionController::RoutingError.new("Not Found") if @dashboard_class.nil? || @dashboard_class.is_hidden?
|
14
|
+
@dashboard = Avo::App.get_dashboard_by_id params[:dashboard_id]
|
28
15
|
|
29
|
-
@dashboard
|
16
|
+
raise ActionController::RoutingError.new("Not Found") if @dashboard.nil? || @dashboard.is_hidden?
|
30
17
|
end
|
31
18
|
|
32
19
|
def set_card
|
33
|
-
@card = @
|
34
|
-
card.hydrate(
|
20
|
+
@card = @dashboard.item_at_index(params[:index].to_i).tap do |card|
|
21
|
+
card.hydrate(dashboard: @dashboard, params: params)
|
35
22
|
end
|
36
23
|
end
|
37
24
|
end
|
@@ -10,11 +10,9 @@ module Avo
|
|
10
10
|
private
|
11
11
|
|
12
12
|
def set_dashboard
|
13
|
-
@
|
13
|
+
@dashboard = Avo::App.get_dashboard_by_id params[:id]
|
14
14
|
|
15
|
-
raise ActionController::RoutingError.new("Not Found") if @
|
16
|
-
|
17
|
-
@dashboard = @dashboard_class.new.hydrate(params: params) if @dashboard_class.present?
|
15
|
+
raise ActionController::RoutingError.new("Not Found") if @dashboard.nil? || @dashboard.is_hidden?
|
18
16
|
end
|
19
17
|
end
|
20
18
|
end
|
@@ -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
|
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
|
File without changes
|
@@ -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)
|
@@ -5,9 +5,9 @@ import ActionsPickerController from './controllers/actions_picker_controller'
|
|
5
5
|
import AttachmentsController from './controllers/attachments_controller'
|
6
6
|
import BelongsToFieldController from './controllers/fields/belongs_to_field_controller'
|
7
7
|
import BooleanFilterController from './controllers/boolean_filter_controller'
|
8
|
-
import CardController from './controllers/card_controller'
|
9
8
|
import CodeFieldController from './controllers/fields/code_field_controller'
|
10
9
|
import CopyToClipboardController from './controllers/copy_to_clipboard_controller'
|
10
|
+
import DashboardCardController from './controllers/dashboard_card_controller'
|
11
11
|
import DateFieldController from './controllers/fields/date_field_controller'
|
12
12
|
import FilterController from './controllers/filter_controller'
|
13
13
|
import HiddenInputController from './controllers/hidden_input_controller'
|
@@ -38,8 +38,8 @@ application.register('action', ActionController)
|
|
38
38
|
application.register('actions-picker', ActionsPickerController)
|
39
39
|
application.register('attachments', AttachmentsController)
|
40
40
|
application.register('boolean-filter', BooleanFilterController)
|
41
|
-
application.register('card', CardController)
|
42
41
|
application.register('copy-to-clipboard', CopyToClipboardController)
|
42
|
+
application.register('dashboard-card', DashboardCardController)
|
43
43
|
application.register('filter', FilterController)
|
44
44
|
application.register('hidden-input', HiddenInputController)
|
45
45
|
application.register('item-select-all', ItemSelectAllController)
|
@@ -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,5 +1,5 @@
|
|
1
|
-
<div class="flex items-end
|
1
|
+
<div class="flex mt-4 items-end">
|
2
2
|
<span class="text-3xl"><%= @card.prefix %></span>
|
3
|
-
<span class="text-5xl
|
3
|
+
<span class="text-5xl"><%= @card.result_data %></span>
|
4
4
|
<span class="text-3xl"><%= @card.suffix %></span>
|
5
5
|
</div>
|