avo 3.0.0.pre12 → 3.0.0.pre15
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of avo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -1
- data/app/assets/stylesheets/avo.base.css +1 -1
- data/app/components/avo/actions_component.html.erb +1 -1
- data/app/components/avo/actions_component.rb +40 -16
- data/app/components/avo/alert_component.html.erb +1 -1
- data/app/components/avo/base_component.rb +7 -7
- data/app/components/avo/field_wrapper_component.html.erb +2 -2
- data/app/components/avo/field_wrapper_component.rb +1 -1
- data/app/components/avo/fields/area_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +5 -5
- data/app/components/avo/fields/belongs_to_field/edit_component.rb +4 -4
- data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/code_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/common/heading_component.html.erb +1 -1
- data/app/components/avo/fields/country_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/file_field/index_component.rb +2 -2
- data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -0
- data/app/components/avo/fields/index_component.rb +1 -0
- data/app/components/avo/fields/location_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/markdown_field/edit_component.html.erb +4 -3
- data/app/components/avo/fields/markdown_field/show_component.html.erb +3 -3
- data/app/components/avo/fields/number_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/password_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/text_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/textarea_field/edit_component.html.erb +1 -0
- data/app/components/avo/fields/trix_field/edit_component.html.erb +2 -1
- data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
- data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
- data/app/components/avo/index/grid_item_component.html.erb +9 -35
- data/app/components/avo/index/grid_item_component.rb +36 -10
- data/app/components/avo/index/resource_controls_component.rb +6 -6
- data/app/components/avo/index/resource_table_component.rb +1 -1
- data/app/components/avo/item_switcher_component.html.erb +9 -4
- data/app/components/avo/item_switcher_component.rb +2 -1
- data/app/components/avo/panel_component.html.erb +1 -1
- data/app/components/avo/profile_item_component.html.erb +17 -2
- data/app/components/avo/profile_item_component.rb +13 -1
- data/app/components/avo/resource_component.rb +6 -3
- data/app/components/avo/resource_sidebar_component.rb +1 -1
- data/app/components/avo/row_component.html.erb +3 -0
- data/app/components/avo/row_component.rb +12 -0
- data/app/components/avo/sidebar/link_component.html.erb +2 -0
- data/app/components/avo/sidebar/link_component.rb +5 -3
- data/app/components/avo/sidebar_component.html.erb +3 -3
- data/app/components/avo/sidebar_component.rb +4 -4
- data/app/components/avo/sidebar_profile_component.html.erb +27 -27
- data/app/components/avo/views/resource_edit_component.rb +1 -1
- data/app/components/avo/views/resource_index_component.html.erb +1 -1
- data/app/components/avo/views/resource_index_component.rb +8 -8
- data/app/controllers/avo/actions_controller.rb +16 -8
- data/app/controllers/avo/application_controller.rb +71 -66
- data/app/controllers/avo/associations_controller.rb +4 -6
- data/app/controllers/avo/attachments_controller.rb +1 -1
- data/app/controllers/avo/base_controller.rb +39 -27
- data/app/controllers/avo/home_controller.rb +1 -1
- data/app/controllers/avo/search_controller.rb +18 -20
- data/app/controllers/concerns/avo/initializes_avo.rb +3 -6
- data/app/javascript/js/controllers/fields/{simple_mde_controller.js → easy_mde_controller.js} +4 -3
- data/app/javascript/js/controllers/search_controller.js +3 -1
- data/app/javascript/js/controllers.js +2 -2
- data/app/views/avo/actions/show.html.erb +2 -1
- data/app/views/avo/associations/new.html.erb +1 -1
- data/app/views/avo/debug/status.html.erb +1 -1
- data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
- data/app/views/avo/partials/_footer.html.erb +1 -1
- data/app/views/avo/partials/_javascript.html.erb +1 -1
- data/app/views/avo/partials/_navbar.html.erb +1 -1
- data/app/views/avo/partials/_profile_menu_extra.html.erb +2 -0
- data/app/views/layouts/avo/application.html.erb +2 -2
- data/avo.gemspec +1 -0
- data/config/initializers/pagy.rb +12 -10
- data/config/routes.rb +3 -3
- data/db/factories.rb +2 -1
- data/lib/avo/base_action.rb +12 -3
- data/lib/avo/base_resource.rb +183 -181
- data/lib/avo/concerns/filters_session_handler.rb +0 -1
- data/lib/avo/concerns/has_item_type.rb +4 -0
- data/lib/avo/concerns/has_items.rb +28 -23
- data/lib/avo/concerns/model_class_constantized.rb +0 -2
- data/lib/avo/configuration.rb +6 -2
- data/lib/avo/current.rb +29 -2
- data/lib/avo/dsl/field_parser.rb +1 -1
- data/lib/avo/dynamic_router.rb +12 -1
- data/lib/avo/engine.rb +8 -6
- data/lib/avo/execution_context.rb +1 -1
- data/lib/avo/fields/base_field.rb +25 -7
- data/lib/avo/fields/belongs_to_field.rb +20 -13
- data/lib/avo/fields/concerns/is_searchable.rb +1 -1
- data/lib/avo/fields/concerns/use_resource.rb +1 -1
- data/lib/avo/fields/field_manager.rb +13 -3
- data/lib/avo/fields/has_base_field.rb +5 -5
- data/lib/avo/fields/has_one_field.rb +1 -1
- data/lib/avo/fields/location_field.rb +18 -1
- data/lib/avo/filters/base_filter.rb +3 -1
- data/lib/avo/html/builder.rb +3 -1
- data/lib/avo/licensing/h_q.rb +11 -6
- data/lib/avo/licensing/license.rb +1 -1
- data/lib/avo/licensing/license_manager.rb +1 -1
- data/lib/avo/licensing/{null_license.rb → nil_license.rb} +1 -1
- data/lib/avo/loaders/fields_loader.rb +7 -1
- data/lib/avo/plugin_manager.rb +2 -4
- data/lib/avo/reloader.rb +1 -1
- data/lib/avo/resources/controls/actions_list.rb +2 -1
- data/lib/avo/resources/items/holder.rb +5 -1
- data/lib/avo/resources/items/item_group.rb +1 -0
- data/lib/avo/resources/items/row.rb +54 -0
- data/lib/avo/resources/resource_manager.rb +4 -7
- data/lib/avo/services/debug_service.rb +6 -6
- data/lib/avo/services/telemetry_service.rb +3 -3
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +107 -25
- data/lib/generators/avo/action_generator.rb +8 -8
- data/lib/generators/avo/card_generator.rb +27 -0
- data/lib/generators/avo/eject_generator.rb +1 -0
- data/lib/generators/avo/filter_generator.rb +8 -8
- data/lib/generators/avo/install_generator.rb +0 -1
- data/lib/generators/avo/resource_generator.rb +4 -1
- data/lib/generators/avo/templates/action.tt +3 -3
- data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
- data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
- data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
- data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
- data/lib/generators/avo/templates/dashboards/dashboard.tt +1 -1
- data/lib/generators/avo/templates/resource/resource.tt +3 -4
- data/lib/generators/avo/templates/scope.tt +1 -1
- data/lib/tasks/avo_tasks.rake +1 -1
- data/public/avo-assets/avo.base.css +295 -165
- data/public/avo-assets/avo.base.js +307 -278
- data/public/avo-assets/avo.base.js.map +3 -3
- metadata +23 -10
- data/lib/avo/app.rb +0 -170
- data/lib/avo/grid_collector.rb +0 -40
- data/lib/generators/avo/card/chartkick_generator.rb +0 -18
- data/lib/generators/avo/card/metric_generator.rb +0 -18
- data/lib/generators/avo/card/partial_generator.rb +0 -19
- data/lib/generators/avo/templates/standalone_action.tt +0 -15
@@ -2,30 +2,26 @@
|
|
2
2
|
|
3
3
|
class Avo::Index::GridItemComponent < Avo::BaseComponent
|
4
4
|
include Avo::ResourcesHelper
|
5
|
+
include Avo::Fields::Concerns::HasHTMLAttributes
|
5
6
|
|
6
7
|
attr_reader :parent_resource, :actions
|
7
8
|
|
8
9
|
def initialize(resource: nil, reflection: nil, parent_record: nil, parent_resource: nil, actions: nil)
|
9
10
|
@resource = resource
|
10
11
|
@reflection = reflection
|
11
|
-
@grid_fields = resource.get_grid_fields
|
12
12
|
@parent_record = parent_record
|
13
13
|
@parent_resource = parent_resource
|
14
14
|
@actions = actions
|
15
|
+
@card = Avo::ExecutionContext.new(target: resource.grid_view[:card], resource: resource, record: resource.record).handle
|
16
|
+
@whole_html = Avo::ExecutionContext.new(target: resource.grid_view[:html], resource: resource, record: resource.record).handle
|
15
17
|
end
|
16
18
|
|
17
19
|
private
|
18
20
|
|
19
|
-
def
|
20
|
-
@
|
21
|
-
end
|
22
|
-
|
23
|
-
def title
|
24
|
-
@grid_fields.title_field
|
25
|
-
end
|
21
|
+
def html(element, type)
|
22
|
+
return "" if @whole_html.nil? || (@html = @whole_html[element]).nil?
|
26
23
|
|
27
|
-
|
28
|
-
@grid_fields.body_field
|
24
|
+
get_html(type, view: :index, element: :wrapper)
|
29
25
|
end
|
30
26
|
|
31
27
|
def resource_view_path
|
@@ -40,4 +36,34 @@ class Avo::Index::GridItemComponent < Avo::BaseComponent
|
|
40
36
|
|
41
37
|
helpers.resource_view_path(record: @resource.record, resource: parent_or_child_resource, **args)
|
42
38
|
end
|
39
|
+
|
40
|
+
def render_cover
|
41
|
+
return link_to_cover if @card[:cover_url].present?
|
42
|
+
|
43
|
+
link_to resource_view_path do
|
44
|
+
render Avo::Index::GridCoverEmptyStateComponent.new
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def link_to_cover
|
49
|
+
classes = "absolute h-full w-full object-cover"
|
50
|
+
|
51
|
+
link_to image_tag(@card[:cover_url], class: classes), resource_view_path, class: classes, title: @card[:title]
|
52
|
+
end
|
53
|
+
|
54
|
+
def render_title
|
55
|
+
return if @card[:title].blank?
|
56
|
+
|
57
|
+
content_tag :div, class: "grid font-semibold leading-tight text-lg mb-2 #{html(:title, :classes)}", style: html(:title, :style) do
|
58
|
+
link_to @card[:title], resource_view_path
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def render_body
|
63
|
+
return if @card[:body].blank?
|
64
|
+
|
65
|
+
content_tag :div, class: "text-sm break-words text-gray-500 #{html(:body, :classes)}", style: html(:body, :style) do
|
66
|
+
@card[:body]
|
67
|
+
end
|
68
|
+
end
|
43
69
|
end
|
@@ -44,7 +44,7 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
|
|
44
44
|
}
|
45
45
|
end
|
46
46
|
|
47
|
-
helpers.resource_path(record: @resource.record, resource: parent_or_child_resource
|
47
|
+
helpers.resource_path(record: @resource.record, resource: parent_or_child_resource, **args)
|
48
48
|
end
|
49
49
|
|
50
50
|
def edit_path
|
@@ -73,7 +73,7 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
|
|
73
73
|
return @parent_resource if @parent_resource.present?
|
74
74
|
return nil if @parent_record.blank?
|
75
75
|
|
76
|
-
|
76
|
+
Avo.resource_manager.get_resource_by_model_class @parent_record.class
|
77
77
|
end
|
78
78
|
|
79
79
|
def is_has_many_association
|
@@ -81,11 +81,11 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def referrer_path
|
84
|
-
Avo
|
84
|
+
Avo.root_path(paths: ["resources", params[:resource_name], params[:id], params[:related_name]], query: request.query_parameters.to_h)
|
85
85
|
end
|
86
86
|
|
87
87
|
def can_reorder?
|
88
|
-
return false unless Object.const_defined? "
|
88
|
+
return false unless Object.const_defined? "Avo::Pro::Ordering"
|
89
89
|
|
90
90
|
return authorize_association_for(:reorder) if @reflection.present?
|
91
91
|
|
@@ -167,13 +167,13 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
|
|
167
167
|
target: "control:detach",
|
168
168
|
control: :detach,
|
169
169
|
"resource-id": @resource.record.id,
|
170
|
-
|
170
|
+
tippy: :tooltip,
|
171
171
|
}
|
172
172
|
end
|
173
173
|
|
174
174
|
def render_order_controls(control)
|
175
175
|
if can_reorder?
|
176
|
-
render
|
176
|
+
render Avo::Pro::Ordering::ButtonsComponent.new resource: @resource, reflection: @reflection, view_type: @view_type
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
@@ -17,7 +17,7 @@ class Avo::Index::ResourceTableComponent < ViewComponent::Base
|
|
17
17
|
|
18
18
|
def encrypted_query
|
19
19
|
# TODO: move this to the resource where we can apply the adapter pattern
|
20
|
-
serialized_query = if query.instance_of?(Ransack::Search)
|
20
|
+
serialized_query = if Module.const_defined?("Ransack::Search") && query.instance_of?(Ransack::Search)
|
21
21
|
query.context.object.to_sql
|
22
22
|
else
|
23
23
|
return :select_all_disabled if query.nil? || !query.respond_to?(:all) || !query.all.respond_to?(:to_sql)
|
@@ -7,10 +7,7 @@
|
|
7
7
|
<% c.with_body do %>
|
8
8
|
<div class="divide-y">
|
9
9
|
<% item.visible_items.each_with_index do |field, index| %>
|
10
|
-
<%= render field
|
11
|
-
.hydrate(resource: @resource, record: @resource.record, user: resource.user, view: view)
|
12
|
-
.component_for_view(view)
|
13
|
-
.new(field: field, resource: @resource, index: index, form: form) %>
|
10
|
+
<%= render Avo::ItemSwitcherComponent.new resource: @resource, item: field, index: index, view: @view, form: form %>
|
14
11
|
<% end %>
|
15
12
|
</div>
|
16
13
|
<% end %>
|
@@ -19,4 +16,12 @@
|
|
19
16
|
<%= render tab_group_component %>
|
20
17
|
<% elsif item.is_field? %>
|
21
18
|
<%= render field_component %>
|
19
|
+
<% elsif item.is_row? %>
|
20
|
+
<%= render Avo::RowComponent.new do |c| %>
|
21
|
+
<% c.with_body do %>
|
22
|
+
<% item.visible_items.each_with_index do |field, index| %>
|
23
|
+
<%= render Avo::ItemSwitcherComponent.new resource: @resource, item: field, index: index, view: @view, form: form %>
|
24
|
+
<% end %>
|
25
|
+
<% end %>
|
26
|
+
<% end %>
|
22
27
|
<% end %>
|
@@ -42,6 +42,7 @@ class Avo::ItemSwitcherComponent < Avo::BaseComponent
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def field_component
|
45
|
-
item.
|
45
|
+
final_item = item.dup.hydrate(resource: @resource, record: @resource.record, user: resource.user, view: view)
|
46
|
+
final_item.component_for_view(@view).new(field: final_item, resource: @resource, index: index, form: form)
|
46
47
|
end
|
47
48
|
end
|
@@ -25,7 +25,7 @@
|
|
25
25
|
<% end %>
|
26
26
|
<% if body? %>
|
27
27
|
<div data-target="panel-body" class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:gap-4 w-full">
|
28
|
-
<div class="relative flex-1 <% if sidebar? %> w-2/3 <%
|
28
|
+
<div class="relative flex-1 w-full <% if sidebar? %> sm:w-2/3 <% end %>">
|
29
29
|
<% # The body is wrapped inside another div in order to avoid long & tall panels next to sidebars when the sidebar taller. %>
|
30
30
|
<div class="relative <%= white_panel_classes %> <%= @body_classes %>">
|
31
31
|
<%= body %>
|
@@ -1,3 +1,18 @@
|
|
1
|
-
|
2
|
-
<%=
|
1
|
+
<% if method.present? %>
|
2
|
+
<%= button_to path,
|
3
|
+
form_class: "flex-1 flex",
|
4
|
+
class: button_classes,
|
5
|
+
target: target,
|
6
|
+
title: title,
|
7
|
+
method: method,
|
8
|
+
params: params do %>
|
9
|
+
<%= helpers.svg(icon, class: 'h-4 mr-1') if icon.present? %> <%= label %>
|
10
|
+
<% end %>
|
11
|
+
<% else %>
|
12
|
+
<%= link_to path,
|
13
|
+
class: button_classes,
|
14
|
+
target: target,
|
15
|
+
title: title do %>
|
16
|
+
<%= helpers.svg(icon, class: 'h-4 mr-1') if icon.present? %> <%= label %>
|
17
|
+
<% end %>
|
3
18
|
<% end %>
|
@@ -6,17 +6,29 @@ class Avo::ProfileItemComponent < ViewComponent::Base
|
|
6
6
|
attr_reader :path
|
7
7
|
attr_reader :active
|
8
8
|
attr_reader :target
|
9
|
+
attr_reader :method
|
10
|
+
attr_reader :params
|
11
|
+
attr_reader :classes
|
9
12
|
|
10
|
-
def initialize(label: nil, icon: nil, path: nil, active: :inclusive, target: nil, title: nil)
|
13
|
+
def initialize(label: nil, icon: nil, path: nil, active: :inclusive, target: nil, title: nil, method: nil, params: {}, classes: "")
|
11
14
|
@label = label
|
12
15
|
@icon = icon
|
13
16
|
@path = path
|
14
17
|
@active = active
|
15
18
|
@target = target
|
16
19
|
@title = title
|
20
|
+
@method = method
|
21
|
+
@params = params
|
22
|
+
@classes = classes
|
17
23
|
end
|
18
24
|
|
19
25
|
def title
|
20
26
|
@title || @label
|
21
27
|
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def button_classes
|
32
|
+
"flex-1 flex items-center justify-center bg-white text-left cursor-pointer text-gray-800 font-semibold hover:bg-primary-100 block px-4 py-1 w-full py-3 text-center rounded w-full"
|
33
|
+
end
|
22
34
|
end
|
@@ -102,7 +102,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def sidebar
|
105
|
-
return if Avo
|
105
|
+
return if Avo.license.lacks_with_trial(:resource_sidebar)
|
106
106
|
|
107
107
|
@sidebar ||= search_for_sidebar
|
108
108
|
end
|
@@ -113,7 +113,8 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
113
113
|
|
114
114
|
def has_reflection_and_is_read_only
|
115
115
|
if @reflection.present? && @reflection.active_record.name && @reflection.name
|
116
|
-
|
116
|
+
resource = Avo.resource_manager.get_resource_by_model_class(@reflection.active_record.name).new(params: helpers.params, view: view, user: helpers._current_user)
|
117
|
+
fields = resource.get_field_definitions
|
117
118
|
filtered_fields = fields.filter { |f| f.id == @reflection.name }
|
118
119
|
else
|
119
120
|
return false
|
@@ -165,6 +166,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
165
166
|
resource: @resource,
|
166
167
|
view: @view,
|
167
168
|
exclude: actions_list.exclude,
|
169
|
+
include: actions_list.include,
|
168
170
|
style: actions_list.style,
|
169
171
|
color: actions_list.color,
|
170
172
|
label: actions_list.label,
|
@@ -286,7 +288,8 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
286
288
|
end
|
287
289
|
|
288
290
|
def render_action(action)
|
289
|
-
return
|
291
|
+
return if !can_see_the_actions_button?
|
292
|
+
return if !action.action.visible_in_view(parent_resource: @parent_resource)
|
290
293
|
|
291
294
|
a_link action.path,
|
292
295
|
color: action.color,
|
@@ -1,5 +1,6 @@
|
|
1
1
|
<% if path.present? %>
|
2
2
|
<%= send link_method, path, class: classes, active: active, target: target, data: data do %>
|
3
|
+
<%= helpers.svg icon, class: "h-4 text-gray-700" if icon.present? %>
|
3
4
|
<%= label %>
|
4
5
|
<% if target == :_blank %>
|
5
6
|
<%= helpers.svg('heroicons/outline/external-link', class: 'self-center ml-auto h-3 mr-2') %>
|
@@ -7,6 +8,7 @@
|
|
7
8
|
<% end %>
|
8
9
|
<% else %>
|
9
10
|
<%= content_tag :div, class: classes, active: active, target: target, data: data do %>
|
11
|
+
<%= helpers.svg icon, class: "h-4 text-gray-700" if icon.present? %>
|
10
12
|
<%= label %>
|
11
13
|
<% end %>
|
12
14
|
<% end %>
|
@@ -6,18 +6,20 @@ class Avo::Sidebar::LinkComponent < ViewComponent::Base
|
|
6
6
|
attr_reader :label
|
7
7
|
attr_reader :path
|
8
8
|
attr_reader :data
|
9
|
+
attr_reader :icon
|
9
10
|
|
10
|
-
def initialize(label: nil, path: nil, active: :inclusive, target: nil, data: {})
|
11
|
+
def initialize(label: nil, path: nil, active: :inclusive, target: nil, data: {}, icon: nil)
|
11
12
|
@label = label
|
12
13
|
@path = path
|
13
14
|
@active = active
|
14
15
|
@target = target
|
15
16
|
@data = data
|
17
|
+
@icon = icon
|
16
18
|
end
|
17
19
|
|
18
20
|
def is_external?
|
19
21
|
# If the path contains the scheme, check if it includes the root path or not
|
20
|
-
return !path.include?(Avo
|
22
|
+
return !path.include?(Avo.mount_path) if URI(path).scheme.present?
|
21
23
|
|
22
24
|
false
|
23
25
|
end
|
@@ -28,6 +30,6 @@ class Avo::Sidebar::LinkComponent < ViewComponent::Base
|
|
28
30
|
end
|
29
31
|
|
30
32
|
def classes
|
31
|
-
"px-4 pr-0 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-100"
|
33
|
+
"px-4 pr-0 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-100 gap-1"
|
32
34
|
end
|
33
35
|
end
|
@@ -13,8 +13,8 @@
|
|
13
13
|
<div class="space-y-6 mb-4">
|
14
14
|
<%= render Avo::Sidebar::LinkComponent.new label: 'Get started', path: helpers.avo.root_path, active: :exclusive if Rails.env.development? && Avo.configuration.home_path.nil? %>
|
15
15
|
|
16
|
-
<% if Avo.plugin_manager.installed?(
|
17
|
-
<% Avo
|
16
|
+
<% if Avo.plugin_manager.installed?("avo-menu") && Avo.has_main_menu? %>
|
17
|
+
<% Avo.main_menu.items.each do |item| %>
|
18
18
|
<%= render Avo::Sidebar::ItemSwitcherComponent.new item: item %>
|
19
19
|
<% end %>
|
20
20
|
<% else %>
|
@@ -60,7 +60,7 @@
|
|
60
60
|
<% if Rails.env.development? %>
|
61
61
|
<div class="p-4 border-t group">
|
62
62
|
<%= link_to helpers.avo.avo_private_status_path, class: "block px-4 py-2 border rounded flex justify-between items-center w-full text-black text-sm" do %>
|
63
|
-
<span>Avo Status</span> <span><div class="rounded-full w-4 h-4 <%= Avo
|
63
|
+
<span>Avo Status</span> <span><div class="rounded-full w-4 h-4 <%= Avo.app_status ? "bg-green-400" : "bg-orange-400" %>"></div></span>
|
64
64
|
<% end %>
|
65
65
|
<div class="absolute text-xs text-gray-700 group-hover:block hidden text-center w-full -ml-4">👆Visible only in development👆</div>
|
66
66
|
</div>
|
@@ -7,17 +7,17 @@ class Avo::SidebarComponent < ViewComponent::Base
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def dashboards
|
10
|
-
return [] unless defined?(
|
10
|
+
return [] unless defined?(Avo::Dashboards)
|
11
11
|
|
12
|
-
|
12
|
+
Avo::Dashboards.dashboard_manager.dashboards_for_navigation
|
13
13
|
end
|
14
14
|
|
15
15
|
def resources
|
16
|
-
Avo
|
16
|
+
Avo.resource_manager.resources_for_navigation helpers._current_user
|
17
17
|
end
|
18
18
|
|
19
19
|
def tools
|
20
|
-
Avo
|
20
|
+
Avo.tool_manager.tools_for_navigation
|
21
21
|
end
|
22
22
|
|
23
23
|
def stimulus_target
|
@@ -16,32 +16,32 @@
|
|
16
16
|
<% end %>
|
17
17
|
</div>
|
18
18
|
</div>
|
19
|
-
|
20
|
-
<
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
<% Avo::
|
37
|
-
|
38
|
-
<%= render Avo::ProfileItemComponent.new label: item.name, path: item.path, icon: item.icon %>
|
39
|
-
<% end %>
|
19
|
+
<div class="relative" data-controller="toggle">
|
20
|
+
<a class="flex items-center h-full cursor-pointer" data-control="profile-dots" data-action="click->toggle#togglePanel">
|
21
|
+
<%= helpers.svg 'three-dots', class: 'h-4' %>
|
22
|
+
</a>
|
23
|
+
<div
|
24
|
+
class="hidden absolute flex flex-col inset-auto right-0 -mt-12 bg-white rounded min-w-[200px] shadow-context -translate-y-full z-40"
|
25
|
+
data-toggle-target="panel"
|
26
|
+
data-transition-enter="transition ease-out duration-100"
|
27
|
+
data-transition-enter-start="transform opacity-0 translate-y-1"
|
28
|
+
data-transition-enter-end="transform opacity-100 translate-y-0"
|
29
|
+
data-transition-leave="transition ease-in duration-75"
|
30
|
+
data-transition-leave-start="transform opacity-100 translate-y-0"
|
31
|
+
data-transition-leave-end="transform opacity-0 translate-y-1"
|
32
|
+
>
|
33
|
+
<% if Avo.plugin_manager.installed?("avo-menu") && Avo.has_profile_menu? %>
|
34
|
+
<div class="text-black space-y-4">
|
35
|
+
<% Avo.profile_menu.items.each do |item| %>
|
36
|
+
<% if item.is_a? Avo::Menu::Link %>
|
37
|
+
<%= render Avo::ProfileItemComponent.new label: item.name, path: item.path, icon: item.icon, method: item.method, params: item.params %>
|
40
38
|
<% end %>
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
<% end %>
|
40
|
+
</div>
|
41
|
+
<% end %>
|
42
|
+
<%# Example link below %>
|
43
|
+
<%#= render Avo::ProfileItemComponent.new label: 'Profile', path: '/profile', icon: 'user-circle' %>
|
44
|
+
<% if can_destroy_user? %>
|
45
45
|
<%= button_to helpers.main_app.send(destroy_user_session_path),
|
46
46
|
form: { "data-turbo" => "false" },
|
47
47
|
method: :delete,
|
@@ -52,7 +52,7 @@
|
|
52
52
|
form_class: 'flex-1' do %>
|
53
53
|
<%= helpers.svg 'logout', class: 'h-4 mr-1' %> <%= t('avo.sign_out') %>
|
54
54
|
<% end %>
|
55
|
-
|
55
|
+
<% end %>
|
56
56
|
</div>
|
57
|
-
|
57
|
+
</div>
|
58
58
|
</div>
|
@@ -79,6 +79,6 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
|
|
79
79
|
|
80
80
|
# Render :show view for read only trix fields
|
81
81
|
def view_for(field)
|
82
|
-
|
82
|
+
field.is_a?(Avo::Fields::TrixField) && field.is_disabled? ? :show : view
|
83
83
|
end
|
84
84
|
end
|
@@ -34,7 +34,7 @@
|
|
34
34
|
</div>
|
35
35
|
</div>
|
36
36
|
<% if Avo.avo_filters_installed? && resource.has_filters? %>
|
37
|
-
<%= render
|
37
|
+
<%= render Avo::DynamicFilters::FiltersComponent.new resource: resource, turbo_frame: turbo_frame %>
|
38
38
|
<% end %>
|
39
39
|
</div>
|
40
40
|
</div>
|
@@ -100,7 +100,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
100
100
|
def attach_path
|
101
101
|
current_path = CGI.unescape(request.env["PATH_INFO"]).split("/").select(&:present?)
|
102
102
|
|
103
|
-
Avo
|
103
|
+
Avo.root_path(paths: [*current_path, "new"])
|
104
104
|
end
|
105
105
|
|
106
106
|
def singular_resource_name
|
@@ -126,7 +126,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
126
126
|
|
127
127
|
def show_search_input
|
128
128
|
return false unless authorized_to_search?
|
129
|
-
return false unless resource.search_query.present?
|
129
|
+
return false unless resource.class.search_query.present?
|
130
130
|
return false if field&.hide_search_input
|
131
131
|
|
132
132
|
true
|
@@ -143,7 +143,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
143
143
|
def render_dynamic_filters_button
|
144
144
|
return unless Avo.avo_filters_installed?
|
145
145
|
return unless resource.has_filters?
|
146
|
-
return if
|
146
|
+
return if Avo::DynamicFilters.configuration.always_expanded
|
147
147
|
|
148
148
|
a_button size: :sm,
|
149
149
|
color: :primary,
|
@@ -152,12 +152,12 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
152
152
|
controller: "avo-filters",
|
153
153
|
action: "click->avo-filters#toggleFiltersArea",
|
154
154
|
} do
|
155
|
-
|
155
|
+
Avo::DynamicFilters.configuration.button_label
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
159
|
def scopes_list
|
160
|
-
|
160
|
+
Avo::Pro::Scopes::ListComponent.new(
|
161
161
|
scopes: scopes,
|
162
162
|
resource: resource,
|
163
163
|
turbo_frame: turbo_frame,
|
@@ -166,7 +166,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
166
166
|
end
|
167
167
|
|
168
168
|
def can_render_scopes?
|
169
|
-
defined?(
|
169
|
+
defined?(Avo::Pro)
|
170
170
|
end
|
171
171
|
|
172
172
|
private
|
@@ -191,11 +191,11 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
191
191
|
end
|
192
192
|
|
193
193
|
def header_visible?
|
194
|
-
search_query_present? || filters_present? || has_many_view_types? || (Avo.avo_filters_installed? && resource.has_filters? &&
|
194
|
+
search_query_present? || filters_present? || has_many_view_types? || (Avo.avo_filters_installed? && resource.has_filters? && Avo::DynamicFilters.configuration.always_expanded)
|
195
195
|
end
|
196
196
|
|
197
197
|
def search_query_present?
|
198
|
-
@resource.search_query.present?
|
198
|
+
@resource.class.search_query.present?
|
199
199
|
end
|
200
200
|
|
201
201
|
def filters_present?
|
@@ -31,12 +31,10 @@ module Avo
|
|
31
31
|
resource: resource
|
32
32
|
}
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@resource.find_record resource_ids, params: params
|
39
|
-
end
|
34
|
+
args[:records] = if @selected_query.present?
|
35
|
+
@resource.model_class.find_by_sql decrypted_query
|
36
|
+
else
|
37
|
+
@resource.find_record resource_ids, params: params
|
40
38
|
end
|
41
39
|
|
42
40
|
performed_action = @action.handle_action(**args)
|
@@ -47,7 +45,7 @@ module Avo
|
|
47
45
|
private
|
48
46
|
|
49
47
|
def action_params
|
50
|
-
params.permit(:authenticity_token, :resource_name, :action_id, fields: {})
|
48
|
+
params.permit(:authenticity_token, :resource_name, :action_id, :button, fields: {})
|
51
49
|
end
|
52
50
|
|
53
51
|
def set_action
|
@@ -56,7 +54,7 @@ module Avo
|
|
56
54
|
resource: @resource,
|
57
55
|
user: _current_user,
|
58
56
|
view: @view,
|
59
|
-
arguments:
|
57
|
+
arguments: decrypted_arguments || {}
|
60
58
|
)
|
61
59
|
end
|
62
60
|
|
@@ -113,6 +111,16 @@ module Avo
|
|
113
111
|
)
|
114
112
|
end
|
115
113
|
|
114
|
+
def decrypted_arguments
|
115
|
+
arguments = params[:arguments] || params.dig(:fields, :arguments)
|
116
|
+
return if arguments.blank?
|
117
|
+
|
118
|
+
Avo::Services::EncryptionService.decrypt(
|
119
|
+
message: Base64.decode64(arguments),
|
120
|
+
purpose: :action_arguments
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
116
124
|
def flash_messages(messages)
|
117
125
|
messages.each do |message|
|
118
126
|
flash[message[:type]] = message[:body]
|