avo 2.9.1.pre5 → 2.10.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 +5 -5
- data/README.md +4 -0
- data/app/assets/stylesheets/css/buttons.css +4 -1
- data/app/components/avo/actions_component.rb +6 -2
- data/app/components/avo/base_component.rb +2 -0
- data/app/components/avo/button_component.rb +3 -1
- data/app/components/avo/fields/common/key_value_component.html.erb +2 -2
- data/app/components/avo/fields/common/single_file_viewer_component.rb +1 -1
- data/app/components/avo/fields/edit_component.rb +5 -0
- data/app/components/avo/fields/show_component.rb +1 -1
- data/app/components/avo/index/ordering/button_component.rb +2 -12
- data/app/components/avo/index/resource_controls_component.html.erb +2 -2
- data/app/components/avo/index/resource_controls_component.rb +5 -1
- data/app/components/avo/index/resource_table_component.html.erb +1 -1
- data/app/components/avo/index/table_row_component.html.erb +1 -1
- data/app/components/avo/item_switcher_component.html.erb +19 -0
- data/app/components/avo/item_switcher_component.rb +45 -0
- data/app/components/avo/panel_component.html.erb +23 -24
- data/app/components/avo/panel_component.rb +8 -5
- data/app/components/avo/tab_group_component.html.erb +53 -0
- data/app/components/avo/tab_group_component.rb +51 -0
- data/app/components/avo/tab_switcher_component.html.erb +21 -0
- data/app/components/avo/tab_switcher_component.rb +86 -0
- data/app/components/avo/views/resource_edit_component.html.erb +34 -56
- data/app/components/avo/views/resource_edit_component.rb +10 -0
- data/app/components/avo/views/resource_index_component.html.erb +1 -1
- data/app/components/avo/views/resource_index_component.rb +3 -3
- data/app/components/avo/views/resource_show_component.html.erb +58 -89
- data/app/components/avo/views/resource_show_component.rb +2 -2
- data/app/controllers/avo/actions_controller.rb +1 -1
- data/app/controllers/avo/application_controller.rb +20 -3
- data/app/helpers/avo/application_helper.rb +0 -6
- data/app/helpers/avo/url_helpers.rb +1 -1
- data/app/javascript/avo.js +5 -1
- data/app/javascript/js/controllers/loading_button_controller.js +25 -21
- data/app/javascript/js/controllers/tabs_controller.js +86 -0
- data/app/javascript/js/controllers.js +2 -0
- data/app/views/avo/base/index.html.erb +1 -1
- data/app/views/avo/base/show.html.erb +1 -1
- data/app/views/avo/cards/show.html.erb +1 -1
- data/app/views/avo/debug/index.html.erb +1 -1
- data/app/views/avo/home/_actions.html.erb +1 -1
- data/app/views/avo/home/_dashboards.html.erb +19 -0
- data/app/views/avo/home/_filters.html.erb +1 -1
- data/app/views/avo/home/_resources.html.erb +1 -1
- data/app/views/avo/home/failed_to_load.html.erb +1 -1
- data/app/views/avo/home/index.html.erb +14 -2
- data/app/views/avo/partials/_javascript.html.erb +1 -1
- data/app/views/avo/partials/_tabs_toggle.html.erb +20 -0
- data/app/views/avo/private/design.html.erb +1 -1
- data/config/routes.rb +1 -1
- data/lib/avo/app.rb +9 -2
- data/lib/avo/base_action.rb +2 -19
- data/lib/avo/base_card.rb +1 -7
- data/lib/avo/base_resource.rb +0 -94
- data/lib/avo/base_resource_tool.rb +3 -1
- data/lib/avo/concerns/has_fields.rb +247 -50
- data/lib/avo/concerns/has_html_attributes.rb +1 -1
- data/lib/avo/concerns/is_resource_item.rb +36 -0
- data/lib/avo/dashboards/base_dashboard.rb +1 -1
- data/lib/avo/dsl/field_parser.rb +83 -0
- data/lib/avo/fields/base_field.rb +19 -2
- data/lib/avo/fields/field_extensions/visible_in_different_views.rb +18 -1
- data/lib/avo/fields/has_base_field.rb +20 -1
- data/lib/avo/fields/has_one_field.rb +4 -1
- data/lib/avo/grid_collector.rb +6 -3
- data/lib/avo/items_holder.rb +68 -0
- data/lib/avo/licensing/h_q.rb +10 -0
- data/lib/avo/main_panel.rb +3 -0
- data/lib/avo/menu/builder.rb +7 -7
- data/lib/avo/panel.rb +25 -0
- data/lib/avo/panel_builder.rb +23 -0
- data/lib/avo/services/uri_service.rb +71 -0
- data/lib/avo/tab.rb +78 -0
- data/lib/avo/tab_builder.rb +25 -0
- data/lib/avo/tab_group.rb +40 -0
- data/lib/avo/tab_group_builder.rb +43 -0
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +1 -0
- data/lib/generators/avo/templates/resource/controller.tt +2 -0
- data/lib/generators/avo/templates/resource_tools/partial.tt +1 -1
- data/lib/generators/avo/templates/tool/view.tt +1 -1
- data/public/avo-assets/avo.css +27 -3
- data/public/avo-assets/avo.js +73 -73
- data/public/avo-assets/avo.js.map +3 -3
- metadata +24 -14
- data/app/assets/builds/action_cable.js +0 -2
- data/app/assets/builds/action_cable.js.map +0 -7
- data/app/assets/builds/application.js +0 -2
- data/app/assets/builds/application.js.map +0 -7
- data/app/assets/builds/avo.css +0 -9028
- data/app/assets/builds/avo.js +0 -512
- data/app/assets/builds/avo.js.map +0 -7
- data/app/assets/builds/avo_custom.js +0 -6
- data/app/assets/builds/avo_custom.js.map +0 -7
- data/lib/avo/concerns/has_tools.rb +0 -47
@@ -0,0 +1,19 @@
|
|
1
|
+
<div>
|
2
|
+
<h3>Dashboards</h3>
|
3
|
+
|
4
|
+
<div>There comes the point in your app's life when you need to display the data in an aggregated form like a metric or chart. That's what Avo's Dashboards are all about.</div>
|
5
|
+
|
6
|
+
<div>Generate a dashboard using the command below 👇👇</div>
|
7
|
+
|
8
|
+
|
9
|
+
<div class="mt-2">
|
10
|
+
<div class="mt-1">
|
11
|
+
<code class="p-1 rounded bg-sky-500 text-white">bin/rails generate avo:dashboard dashy</code>
|
12
|
+
</div>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<p>
|
16
|
+
<a href="https://docs.avohq.io/2.0/dashboards.html" target="_blank" title="Avo Dashboards documentation">Docs</a>
|
17
|
+
</p>
|
18
|
+
</div>
|
19
|
+
|
@@ -11,6 +11,6 @@
|
|
11
11
|
</div>
|
12
12
|
</div>
|
13
13
|
|
14
|
-
<a href="https://docs.avohq.io/
|
14
|
+
<a href="https://docs.avohq.io/2.0/filters.html" target="_blank" title="Avo Filters documentation" class="text-bold cursor-pointer block mt-2">Filters in the docs 👉</a>
|
15
15
|
</div>
|
16
16
|
</div>
|
@@ -35,7 +35,7 @@
|
|
35
35
|
<% end %>
|
36
36
|
|
37
37
|
<p>
|
38
|
-
<a href="https://docs.avohq.io/
|
38
|
+
<a href="https://docs.avohq.io/2.0/resources.html" target="_blank" title="Avo Resources documentation">Docs</a>
|
39
39
|
</p>
|
40
40
|
</div>
|
41
41
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div class="flex flex-col">
|
2
|
-
<%= render Avo::PanelComponent.new
|
2
|
+
<%= render Avo::PanelComponent.new(title: '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">
|
@@ -23,10 +23,20 @@
|
|
23
23
|
<li><span class="mr-2">👍</span> Grid view</li>
|
24
24
|
<li><span class="mr-2">👍</span> Authorization</li>
|
25
25
|
<li><span class="mr-2">👍</span> Localization</li>
|
26
|
+
<li><span class="mr-2">👍</span> Resource tools</li>
|
26
27
|
<li><span class="mr-2">👍</span> Custom tools</li>
|
27
28
|
<li><span class="mr-2">👍</span> Custom fields</li>
|
29
|
+
<li><span class="mr-2">👍</span> Menu editor</li>
|
28
30
|
<li><span class="mr-2">👍</span> Search</li>
|
29
|
-
<li><span class="mr-2"
|
31
|
+
<li><span class="mr-2">👍</span> Dashboards</li>
|
32
|
+
<li><span class="mr-2">👍</span> Responsive design</li>
|
33
|
+
<li><span class="mr-2">👍</span> Menu editor</li>
|
34
|
+
<li><span class="mr-2">👍</span> Stimulus JS integration</li>
|
35
|
+
<li><span class="mr-2">👍</span> Tabs and panels</li>
|
36
|
+
<li><span class="mr-2">🕐</span> Resource cards</li>
|
37
|
+
<li><span class="mr-2">🕐</span> Track resource changes</li>
|
38
|
+
<li><span class="mr-2">🕐</span> Smart resource generation</li>
|
39
|
+
<li><span class="mr-2">🕐</span> Records preview</li>
|
30
40
|
<li><span class="mr-2">🕐</span> Themes</li>
|
31
41
|
</ul>
|
32
42
|
</p>
|
@@ -37,6 +47,8 @@
|
|
37
47
|
<div class="space">
|
38
48
|
<%= render partial: 'resources' %>
|
39
49
|
<hr class="my-6">
|
50
|
+
<%= render partial: 'dashboards' %>
|
51
|
+
<hr class="my-6">
|
40
52
|
<%= render partial: 'filters' %>
|
41
53
|
<hr class="my-6">
|
42
54
|
<%= render partial: 'actions' %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<%= javascript_tag nonce: true do %>
|
2
2
|
window.Avo = window.Avo || { configuration: {} }
|
3
3
|
Avo.configuration.timezone = '<%= Avo.configuration.timezone %>'
|
4
|
-
Avo.configuration.root_path = '<%= Avo
|
4
|
+
Avo.configuration.root_path = '<%= Avo.configuration.root_path %>'
|
5
5
|
Avo.configuration.search_debounce = '<%= Avo.configuration.search_debounce %>'
|
6
6
|
<% end %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<div class="flex">
|
2
|
+
<div class="button-group">
|
3
|
+
<% tabs.each do |tab| %>
|
4
|
+
<% is_active_view = tab.name.to_s == active_tab_name.to_s %>
|
5
|
+
<%= a_link resource_path(resource: @resource, model: @resource.model, keep_query_params: true, active_tab_name: tab.name, tab_turbo_frame: group.turbo_frame_id),
|
6
|
+
color: is_active_view ? :gray : :primary,
|
7
|
+
rounded: false,
|
8
|
+
size: :sm,
|
9
|
+
class: is_active_view ? ' bg-gray-100 border-gray-300' : ' z-20',
|
10
|
+
title: tab.description || tab.name,
|
11
|
+
data: {
|
12
|
+
tippy: 'tooltip',
|
13
|
+
'turbo-frame': group.turbo_frame_id,
|
14
|
+
control: "view-type-toggle-#{tab}"
|
15
|
+
} do %>
|
16
|
+
<%= tab.name %>
|
17
|
+
<% end %>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
20
|
+
</div>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div class="flex flex-col">
|
2
|
-
<%= render Avo::PanelComponent.new
|
2
|
+
<%= render Avo::PanelComponent.new(title: '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
4
|
<%= a_link('/admin', icon: 'arrow-left', style: :primary, is_link: true) do %>
|
5
5
|
Primary
|
data/config/routes.rb
CHANGED
@@ -23,7 +23,7 @@ Avo::Engine.routes.draw do
|
|
23
23
|
delete "/:resource_name/:id/active_storage_attachments/:attachment_name/:attachment_id", to: "attachments#destroy"
|
24
24
|
|
25
25
|
# Ordering
|
26
|
-
patch "/:resource_name/:id/order", to: "resources#order"
|
26
|
+
patch "/:resource_name/:id/order", to: "resources#order", as: "order"
|
27
27
|
patch "/:resource_name/:id/:related_name/:related_id/order", to: "associations#order", as: "associations_order"
|
28
28
|
|
29
29
|
# Actions
|
data/lib/avo/app.rb
CHANGED
@@ -29,13 +29,20 @@ module Avo
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
# Renerate a dynamic root path using the URIService
|
33
|
+
def root_path(paths: [], query: {}, **args)
|
34
|
+
Avo::Services::URIService.parse(view_context.avo.root_url.to_s)
|
35
|
+
.append_paths(paths)
|
36
|
+
.append_query(query)
|
37
|
+
.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def init(request:, context:, current_user:, view_context:, params:)
|
33
41
|
self.error_messages = []
|
34
42
|
self.context = context
|
35
43
|
self.current_user = current_user
|
36
44
|
self.params = params
|
37
45
|
self.request = request
|
38
|
-
self.root_path = root_path
|
39
46
|
self.view_context = view_context
|
40
47
|
|
41
48
|
self.license = Licensing::LicenseManager.new(Licensing::HQ.new(request).response).license
|
data/lib/avo/base_action.rb
CHANGED
@@ -13,7 +13,6 @@ module Avo
|
|
13
13
|
class_attribute :view
|
14
14
|
class_attribute :user
|
15
15
|
class_attribute :resource
|
16
|
-
class_attribute :invalid_fields
|
17
16
|
class_attribute :standalone, default: false
|
18
17
|
class_attribute :visible
|
19
18
|
class_attribute :may_download_file, default: false
|
@@ -22,7 +21,8 @@ module Avo
|
|
22
21
|
attr_accessor :model
|
23
22
|
attr_accessor :resource
|
24
23
|
attr_accessor :user
|
25
|
-
|
24
|
+
|
25
|
+
delegate :view, to: :class
|
26
26
|
|
27
27
|
class << self
|
28
28
|
def form_data_attributes
|
@@ -68,23 +68,6 @@ module Avo
|
|
68
68
|
self.class.context
|
69
69
|
end
|
70
70
|
|
71
|
-
def get_field_definitions
|
72
|
-
return [] if self.class.fields.blank?
|
73
|
-
|
74
|
-
self.class.fields.map do |field|
|
75
|
-
field.hydrate(action: self)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def get_fields
|
80
|
-
get_field_definitions.map do |field|
|
81
|
-
field.hydrate(action: self, model: @model)
|
82
|
-
end
|
83
|
-
.select do |field|
|
84
|
-
field.visible?
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
71
|
def get_attributes_for_action
|
89
72
|
get_fields.map do |field|
|
90
73
|
[field.id, field.value]
|
data/lib/avo/base_card.rb
CHANGED
@@ -59,13 +59,7 @@ module Avo
|
|
59
59
|
def frame_url(enforced_range: nil, params: {})
|
60
60
|
enforced_range ||= initial_range || ranges.first
|
61
61
|
|
62
|
-
|
63
|
-
begin
|
64
|
-
other_params = "&#{params.permit!.to_h.map { |k, v| "#{k}=#{v}" }.join("&")}"
|
65
|
-
rescue
|
66
|
-
end
|
67
|
-
|
68
|
-
"#{Avo::App.root_path}/dashboards/#{dashboard.id}/cards/#{id}?turbo_frame=#{turbo_frame}&index=#{index}&range=#{enforced_range}#{other_params}"
|
62
|
+
Avo::App.view_context.avo.dashboard_card_path(dashboard.id, id, turbo_frame: turbo_frame, index: index, range: enforced_range, **params.permit!)
|
69
63
|
end
|
70
64
|
|
71
65
|
def card_classes
|
data/lib/avo/base_resource.rb
CHANGED
@@ -4,7 +4,6 @@ module Avo
|
|
4
4
|
extend HasContext
|
5
5
|
|
6
6
|
include ActionView::Helpers::UrlHelper
|
7
|
-
include Avo::Concerns::HasTools
|
8
7
|
include Avo::Concerns::HasModel
|
9
8
|
include Avo::Concerns::HasFields
|
10
9
|
include Avo::Concerns::HasStimulusControllers
|
@@ -44,7 +43,6 @@ module Avo
|
|
44
43
|
class_attribute :hide_from_global_search, default: false
|
45
44
|
class_attribute :after_create_path, default: :show
|
46
45
|
class_attribute :after_update_path, default: :show
|
47
|
-
class_attribute :invalid_fields
|
48
46
|
class_attribute :record_selector, default: true
|
49
47
|
class_attribute :keep_filters_panel_open, default: false
|
50
48
|
|
@@ -123,80 +121,6 @@ module Avo
|
|
123
121
|
self
|
124
122
|
end
|
125
123
|
|
126
|
-
def get_field_definitions
|
127
|
-
return [] if self.class.fields.blank?
|
128
|
-
|
129
|
-
fields = self.class.fields.map do |field|
|
130
|
-
field.hydrate(resource: self, panel_name: default_panel_name, user: user)
|
131
|
-
end
|
132
|
-
|
133
|
-
if Avo::App.license.lacks_with_trial(:custom_fields)
|
134
|
-
fields = fields.reject do |field|
|
135
|
-
field.custom?
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
if Avo::App.license.lacks_with_trial(:advanced_fields)
|
140
|
-
fields = fields.reject do |field|
|
141
|
-
field.type == "tags"
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
fields
|
146
|
-
end
|
147
|
-
|
148
|
-
def get_fields(panel: nil, reflection: nil)
|
149
|
-
fields = get_field_definitions
|
150
|
-
.select do |field|
|
151
|
-
field.send("show_on_#{@view}")
|
152
|
-
end
|
153
|
-
.select do |field|
|
154
|
-
field.visible?
|
155
|
-
end
|
156
|
-
.select do |field|
|
157
|
-
is_valid = true
|
158
|
-
|
159
|
-
# Strip out the reflection field in index queries with a parent association.
|
160
|
-
if reflection.present?
|
161
|
-
# regular non-polymorphic association
|
162
|
-
# we're matching the reflection inverse_of foriegn key with the field's foreign_key
|
163
|
-
if field.is_a?(Avo::Fields::BelongsToField)
|
164
|
-
if field.respond_to?(:foreign_key) &&
|
165
|
-
reflection.inverse_of.present? &&
|
166
|
-
reflection.inverse_of.foreign_key == field.foreign_key
|
167
|
-
is_valid = false
|
168
|
-
end
|
169
|
-
|
170
|
-
# polymorphic association
|
171
|
-
if field.respond_to?(:foreign_key) &&
|
172
|
-
field.is_polymorphic? &&
|
173
|
-
reflection.respond_to?(:polymorphic?) &&
|
174
|
-
reflection.inverse_of.foreign_key == field.reflection.foreign_key
|
175
|
-
is_valid = false
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
is_valid
|
181
|
-
end
|
182
|
-
|
183
|
-
if panel.present?
|
184
|
-
fields = fields.select do |field|
|
185
|
-
field.panel_name == panel
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
hydrate_fields(model: @model, view: @view)
|
190
|
-
|
191
|
-
fields
|
192
|
-
end
|
193
|
-
|
194
|
-
def get_field(id)
|
195
|
-
get_field_definitions.find do |f|
|
196
|
-
f.id == id.to_sym
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
124
|
def get_grid_fields
|
201
125
|
return if self.class.grid_loader.blank?
|
202
126
|
|
@@ -215,14 +139,6 @@ module Avo
|
|
215
139
|
self.class.actions_loader.bag
|
216
140
|
end
|
217
141
|
|
218
|
-
def hydrate_fields(model: nil, view: nil)
|
219
|
-
fields.map do |field|
|
220
|
-
field.hydrate(model: @model, view: @view, resource: self)
|
221
|
-
end
|
222
|
-
|
223
|
-
self
|
224
|
-
end
|
225
|
-
|
226
142
|
def default_panel_name
|
227
143
|
return @params[:related_name].capitalize if @params.present? && @params[:related_name].present?
|
228
144
|
|
@@ -236,16 +152,6 @@ module Avo
|
|
236
152
|
end
|
237
153
|
end
|
238
154
|
|
239
|
-
def panels
|
240
|
-
[
|
241
|
-
{
|
242
|
-
name: default_panel_name,
|
243
|
-
type: :fields,
|
244
|
-
in_panel: true
|
245
|
-
}
|
246
|
-
]
|
247
|
-
end
|
248
|
-
|
249
155
|
def class_name_without_resource
|
250
156
|
self.class.name.demodulize.chomp("Resource")
|
251
157
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module Avo
|
2
2
|
class BaseResourceTool
|
3
|
+
include Avo::Concerns::IsResourceItem
|
3
4
|
include Avo::Fields::FieldExtensions::VisibleInDifferentViews
|
4
5
|
|
5
6
|
class_attribute :name
|
6
7
|
class_attribute :partial
|
8
|
+
class_attribute :item_type, default: :tool
|
7
9
|
|
8
10
|
attr_accessor :params
|
9
11
|
attr_accessor :resource
|
@@ -20,7 +22,7 @@ module Avo
|
|
20
22
|
end
|
21
23
|
|
22
24
|
def hydrate(view: nil)
|
23
|
-
@view = view
|
25
|
+
@view = view if view.present?
|
24
26
|
|
25
27
|
self
|
26
28
|
end
|