avo 3.0.0.pre11 → 3.0.0.pre13
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 +1 -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/field_wrapper_component.html.erb +2 -2
- data/app/components/avo/fields/common/heading_component.html.erb +1 -1
- data/app/components/avo/fields/markdown_field/edit_component.html.erb +3 -3
- data/app/components/avo/fields/markdown_field/show_component.html.erb +3 -3
- data/app/components/avo/fields/trix_field/edit_component.html.erb +1 -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/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 +1 -0
- data/app/components/avo/sidebar_profile_component.html.erb +27 -27
- data/app/components/avo/views/resource_edit_component.html.erb +1 -1
- data/app/components/avo/views/resource_index_component.rb +1 -1
- data/app/components/avo/views/resource_show_component.html.erb +1 -1
- data/app/controllers/avo/actions_controller.rb +12 -8
- data/app/controllers/avo/associations_controller.rb +1 -1
- data/app/controllers/avo/base_controller.rb +15 -3
- data/app/controllers/avo/home_controller.rb +1 -1
- data/app/controllers/avo/search_controller.rb +7 -11
- data/app/javascript/js/controllers/fields/{simple_mde_controller.js → easy_mde_controller.js} +3 -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/partials/_profile_menu_extra.html.erb +2 -0
- data/lib/avo/app.rb +1 -1
- data/lib/avo/base_action.rb +8 -1
- data/lib/avo/base_resource.rb +81 -112
- data/lib/avo/concerns/breadcrumbs.rb +2 -2
- data/lib/avo/concerns/filters_session_handler.rb +5 -4
- data/lib/avo/concerns/has_description.rb +23 -0
- data/lib/avo/concerns/has_items.rb +8 -8
- data/lib/avo/configuration.rb +6 -2
- data/lib/avo/engine.rb +5 -0
- data/lib/avo/fields/base_field.rb +0 -4
- data/lib/avo/fields/belongs_to_field.rb +14 -8
- data/lib/avo/fields/has_base_field.rb +1 -1
- data/lib/avo/resources/controls/actions_list.rb +2 -1
- data/lib/avo/services/debug_service.rb +1 -1
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/eject_generator.rb +1 -0
- data/lib/generators/avo/install_generator.rb +0 -1
- data/lib/generators/avo/resource_generator.rb +4 -1
- data/lib/generators/avo/templates/initializer/avo.tt +1 -1
- data/lib/generators/avo/templates/resource/resource.tt +3 -4
- data/lib/tasks/avo_tasks.rake +27 -0
- data/public/avo-assets/avo.base.css +273 -138
- data/public/avo-assets/avo.base.js +245 -217
- data/public/avo-assets/avo.base.js.map +3 -3
- metadata +5 -4
- data/lib/avo/grid_collector.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbf17f6b86663450788938a16475eba907f1a85a400f72d0efd58b59baea131c
|
4
|
+
data.tar.gz: be6d1682124dfbc7a0fdbff863b80caab538b7fdf28768d463169f2acd2fd086
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c47148a510c188098e524e70c1f7782fdb6fdb0ad8592f6d1e7cdf44fb175c6973db23f4672e2361be971639a5943c44309ea69409967ebe427fc558d90367c
|
7
|
+
data.tar.gz: f065601a617923ac787e0d468276d379f2cfd8798f34c9bdd604ed3a8df7c0722ded2f1013a121b0d69c9d75c85ae0b38ed7a61c745509c83264ca1502f8c9b3
|
data/Gemfile.lock
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
@import './../../../node_modules/
|
1
|
+
@import './../../../node_modules/easymde/dist/easymde.min.css';
|
2
2
|
@import './../../../node_modules/tippy.js/dist/tippy.css';
|
3
3
|
@import './../../../node_modules/tippy.js/themes/light.css';
|
4
4
|
@import './../../../node_modules/flatpickr/dist/flatpickr.css';
|
@@ -32,7 +32,7 @@
|
|
32
32
|
>
|
33
33
|
<div data-target="actions-list" class="w-full space divide-y">
|
34
34
|
<% actions.each_with_index do |action, index| %>
|
35
|
-
<%= link_to action_path(action
|
35
|
+
<%= link_to action_path(action),
|
36
36
|
data: {
|
37
37
|
action_name: action.action_name,
|
38
38
|
'turbo-frame': 'actions_show',
|
@@ -4,11 +4,12 @@ class Avo::ActionsComponent < ViewComponent::Base
|
|
4
4
|
include Avo::ApplicationHelper
|
5
5
|
attr_reader :label, :size, :as_row_control
|
6
6
|
|
7
|
-
def initialize(actions: [], resource: nil, view: nil, exclude: [], style: :outline, color: :primary, label: nil, size: :md, as_row_control: false)
|
7
|
+
def initialize(actions: [], resource: nil, view: nil, exclude: [], include: [], style: :outline, color: :primary, label: nil, size: :md, as_row_control: false)
|
8
8
|
@actions = actions || []
|
9
9
|
@resource = resource
|
10
10
|
@view = view
|
11
11
|
@exclude = exclude
|
12
|
+
@include = include
|
12
13
|
@color = color
|
13
14
|
@style = style
|
14
15
|
@label = label || I18n.t("avo.actions")
|
@@ -21,19 +22,25 @@ class Avo::ActionsComponent < ViewComponent::Base
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def actions
|
24
|
-
@
|
25
|
+
if @exclude.present?
|
26
|
+
@actions.reject { |action| action.class.in?(@exclude) }
|
27
|
+
elsif @include.present?
|
28
|
+
@actions.select { |action| action.class.in?(@include) }
|
29
|
+
else
|
30
|
+
@actions
|
31
|
+
end
|
25
32
|
end
|
26
33
|
|
27
34
|
# When running an action for one record we should do it on a special path.
|
28
35
|
# We do that so we get the `record` param inside the action so we can prefill fields.
|
29
|
-
def action_path(
|
30
|
-
return single_record_path(
|
31
|
-
return many_records_path(
|
36
|
+
def action_path(action)
|
37
|
+
return single_record_path(action) if as_row_control
|
38
|
+
return many_records_path(action) unless @resource.has_record_id?
|
32
39
|
|
33
40
|
if on_record_page?
|
34
|
-
single_record_path
|
41
|
+
single_record_path action
|
35
42
|
else
|
36
|
-
many_records_path
|
43
|
+
many_records_path action
|
37
44
|
end
|
38
45
|
end
|
39
46
|
|
@@ -54,17 +61,34 @@ class Avo::ActionsComponent < ViewComponent::Base
|
|
54
61
|
!on_record_page?
|
55
62
|
end
|
56
63
|
|
57
|
-
def single_record_path(
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
64
|
+
def single_record_path(action)
|
65
|
+
action_url(action, @resource.record_path)
|
66
|
+
end
|
67
|
+
|
68
|
+
def many_records_path(action)
|
69
|
+
action_url(action, @resource.records_path)
|
62
70
|
end
|
63
71
|
|
64
|
-
def
|
65
|
-
Avo::Services::URIService.parse(
|
72
|
+
def action_url(action, path)
|
73
|
+
Avo::Services::URIService.parse(path)
|
66
74
|
.append_paths("actions")
|
67
|
-
.append_query(
|
68
|
-
|
75
|
+
.append_query(
|
76
|
+
{
|
77
|
+
action_id: action.param_id,
|
78
|
+
arguments: encrypted_arguments(action)
|
79
|
+
}.compact
|
80
|
+
).to_s
|
81
|
+
end
|
82
|
+
|
83
|
+
# Encrypt the arguments so we can pass them as a query param.
|
84
|
+
# EncryptionService can generate special characters that can break the URL.
|
85
|
+
# We use Base64 to encode the encrypted string so we can safely pass it as a query param and don't break the URL.
|
86
|
+
def encrypted_arguments(action)
|
87
|
+
return if action.arguments.blank?
|
88
|
+
|
89
|
+
Base64.encode64 Avo::Services::EncryptionService.encrypt(
|
90
|
+
message: action.arguments,
|
91
|
+
purpose: :action_arguments
|
92
|
+
)
|
69
93
|
end
|
70
94
|
end
|
@@ -24,13 +24,13 @@
|
|
24
24
|
<div class="text-red-600 mt-2 text-sm"><%= record.errors.full_messages_for(field.id).to_sentence %></div>
|
25
25
|
<% end %>
|
26
26
|
<% if help.present? %>
|
27
|
-
<div class="text-gray-600 mt-2 text-sm"
|
27
|
+
<div class="text-gray-600 mt-2 text-sm"><%= sanitize help %></div>
|
28
28
|
<% end %>
|
29
29
|
<% end %>
|
30
30
|
</div>
|
31
31
|
</div>
|
32
32
|
<% if params[:avo_debug].present? %>
|
33
33
|
<!-- Raw value: -->
|
34
|
-
<!--
|
34
|
+
<!-- <%= sanitize field.value.inspect %> -->
|
35
35
|
<% end %>
|
36
36
|
<% end %>
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args, full_width: true do %>
|
2
|
-
<div data-controller="
|
2
|
+
<div data-controller="easy-mde">
|
3
3
|
<%= @form.text_area @field.id,
|
4
|
-
class: classes("w-full js-has-
|
4
|
+
class: classes("w-full js-has-easy-mde-editor"),
|
5
5
|
data: {
|
6
6
|
view: view,
|
7
|
-
'
|
7
|
+
'easy-mde-target': 'element',
|
8
8
|
'component-options': @field.options.to_json,
|
9
9
|
},
|
10
10
|
disabled: disabled?,
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args, full_width: true do %>
|
2
|
-
<div data-controller="
|
2
|
+
<div data-controller="easy-mde">
|
3
3
|
<%= text_area_tag @field.id, @field.value,
|
4
|
-
class: helpers.input_classes('w-full js-has-
|
4
|
+
class: helpers.input_classes('w-full js-has-easy-mde-editor'),
|
5
5
|
placeholder: @field.placeholder,
|
6
6
|
disabled: disabled?,
|
7
|
-
'data-
|
7
|
+
'data-easy-mde-target': 'element',
|
8
8
|
'data-component-options': @field.options.to_json,
|
9
9
|
'data-view': :show %>
|
10
10
|
</div>
|
@@ -8,7 +8,7 @@
|
|
8
8
|
<%= link_to t('avo.show_content'), 'javascript:void(0);', class: 'font-bold inline-block', data: { action: 'click->hidden-input#showContent' } %>
|
9
9
|
<% end %>
|
10
10
|
<div class="<%= content_classes %> " data-hidden-input-target="content">
|
11
|
-
|
11
|
+
<%= sanitize @field.value %>
|
12
12
|
</div>
|
13
13
|
</div>
|
14
14
|
<% end %>
|
@@ -5,45 +5,19 @@
|
|
5
5
|
data-resource-name="<%= @resource.class.to_s %>"
|
6
6
|
data-record-id="<%= @resource.record.id %>"
|
7
7
|
>
|
8
|
-
<%= content_tag :div,
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
<%= link_to resource_view_path do %>
|
14
|
-
<%= render Avo::Index::GridCoverEmptyStateComponent.new %>
|
15
|
-
<% end %>
|
16
|
-
<% elsif cover.respond_to?(:to_image) && cover.to_image.present? %>
|
17
|
-
<%= link_to_if cover.link_to_resource, image_tag(cover.to_image, class: 'absolute h-full w-full object-cover'), resource_view_path, class: 'absolute h-full w-full object-cover', title: title.value %>
|
18
|
-
<% elsif cover.type == 'file' %>
|
19
|
-
<% if cover.value.attached? && cover.value.representable? %>
|
20
|
-
<%= link_to_if cover.link_to_resource, image_tag(helpers.main_app.url_for(cover.value.variant(resize_to_limit: [480, 480])), class: 'absolute h-full w-full object-cover'), resource_view_path, class: 'absolute h-full w-full object-cover', title: title.value %>
|
21
|
-
<% else %>
|
22
|
-
<%= link_to resource_view_path do %>
|
23
|
-
<%= render Avo::Index::GridCoverEmptyStateComponent.new %>
|
24
|
-
<% end %>
|
25
|
-
<% end %>
|
26
|
-
<% elsif cover.value.present? %>
|
27
|
-
<%= link_to_if cover.link_to_resource, image_tag(cover.value, class: 'absolute h-full w-full object-cover'), resource_view_path, class: 'absolute h-full w-full object-cover', title: title.value %>
|
28
|
-
<% else %>
|
29
|
-
<%= render Avo::Index::GridCoverEmptyStateComponent.new %>
|
30
|
-
<% end %>
|
8
|
+
<%= content_tag :div,
|
9
|
+
class: "relative w-full pb-3/4 rounded-t overflow-hidden #{html(:cover, :classes)}",
|
10
|
+
style: html(:cover, :style) do %>
|
11
|
+
<%== item_selector_input(floating: true, size: :lg) if @resource.record_selector%>
|
12
|
+
<%= render_cover %>
|
31
13
|
<% end %>
|
32
|
-
|
14
|
+
<div class="grid grid-cols-1 place-content-between p-4 h-full">
|
33
15
|
<div class="mb-4 h-full flex flex-col space-between">
|
34
|
-
|
35
|
-
|
36
|
-
<%= link_to_if title.link_to_resource, title.value, resource_view_path %>
|
37
|
-
<% end %>
|
38
|
-
<% end %>
|
39
|
-
<% if body.present? %>
|
40
|
-
<%= content_tag :div, class: "text-sm break-words text-gray-500 #{body.get_html(:classes, view: :index, element: :wrapper)}", style: body.get_html(:style, view: :index, element: :wrapper) do %>
|
41
|
-
<%= body.value %>
|
42
|
-
<% end %>
|
43
|
-
<% end %>
|
16
|
+
<%= render_title %>
|
17
|
+
<%= render_body %>
|
44
18
|
</div>
|
45
19
|
<div class="w-full place-self-end">
|
46
20
|
<%= render(Avo::Index::ResourceControlsComponent.new(resource: @resource, reflection: @reflection, parent_record: @parent_record, parent_resource: @parent_resource, view_type: :grid, actions: actions)) %>
|
47
21
|
</div>
|
48
|
-
|
22
|
+
</div>
|
49
23
|
</div>
|
@@ -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
|
@@ -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
|
@@ -165,6 +165,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
165
165
|
resource: @resource,
|
166
166
|
view: @view,
|
167
167
|
exclude: actions_list.exclude,
|
168
|
+
include: actions_list.include,
|
168
169
|
style: actions_list.style,
|
169
170
|
color: actions_list.color,
|
170
171
|
label: actions_list.label,
|
@@ -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
|
-
<%
|
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::App.has_profile_menu? %>
|
34
|
+
<div class="text-black space-y-4">
|
35
|
+
<% Avo::App.profile_menu.items.each do |item| %>
|
36
|
+
<% if item.is_a? AvoMenu::Link %>
|
37
|
+
<%= render Avo::ProfileItemComponent.new label: item.name, path: item.path, icon: item.icon %>
|
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>
|
@@ -18,7 +18,7 @@
|
|
18
18
|
multipart: true do |form| %>
|
19
19
|
<%= render Avo::ReferrerParamsComponent.new back_path: back_path %>
|
20
20
|
<%= content_tag :div, class: 'space-y-12' do %>
|
21
|
-
<%= render Avo::PanelComponent.new(name: title, description: @resource.
|
21
|
+
<%= render Avo::PanelComponent.new(name: title, description: @resource.description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
|
22
22
|
<% c.with_tools do %>
|
23
23
|
<% @resource.render_edit_controls.each do |control| %>
|
24
24
|
<%= render_control control %>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
selected_resources: [@resource.record.id],
|
8
8
|
**@resource.stimulus_data_attributes
|
9
9
|
} do %>
|
10
|
-
<%= render Avo::PanelComponent.new(name: title, description: @resource.
|
10
|
+
<%= render Avo::PanelComponent.new(name: title, description: @resource.description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
|
11
11
|
<% c.with_tools do %>
|
12
12
|
<% @resource.render_show_controls.each do |control| %>
|
13
13
|
<%= render_control control %>
|
@@ -56,7 +56,7 @@ module Avo
|
|
56
56
|
resource: @resource,
|
57
57
|
user: _current_user,
|
58
58
|
view: @view,
|
59
|
-
arguments:
|
59
|
+
arguments: decrypted_arguments || {}
|
60
60
|
)
|
61
61
|
end
|
62
62
|
|
@@ -82,13 +82,7 @@ module Avo
|
|
82
82
|
flash_messages messages
|
83
83
|
|
84
84
|
if response[:type] == :redirect
|
85
|
-
|
86
|
-
|
87
|
-
if path.respond_to? :call
|
88
|
-
path = instance_eval(&path)
|
89
|
-
end
|
90
|
-
|
91
|
-
redirect_to path
|
85
|
+
redirect_to Avo::ExecutionContext.new(target: response[:path]).handle
|
92
86
|
elsif response[:type] == :reload
|
93
87
|
redirect_back fallback_location: resources_path(resource: @resource)
|
94
88
|
end
|
@@ -119,6 +113,16 @@ module Avo
|
|
119
113
|
)
|
120
114
|
end
|
121
115
|
|
116
|
+
def decrypted_arguments
|
117
|
+
arguments = params[:arguments] || params.dig(:fields, :arguments)
|
118
|
+
return if arguments.blank?
|
119
|
+
|
120
|
+
Avo::Services::EncryptionService.decrypt(
|
121
|
+
message: Base64.decode64(arguments),
|
122
|
+
purpose: :action_arguments
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
122
126
|
def flash_messages(messages)
|
123
127
|
messages.each do |message|
|
124
128
|
flash[message[:type]] = message[:body]
|
@@ -47,7 +47,7 @@ module Avo
|
|
47
47
|
field_id = @index_params[:sort_by].to_sym
|
48
48
|
field = @resource.get_field_definitions.find { |field| field.id == field_id }
|
49
49
|
@query = if field&.sortable.is_a?(Proc)
|
50
|
-
field.sortable
|
50
|
+
Avo::ExecutionContext.new(target: field.sortable, query: @query, direction: @index_params[:sort_direction]).handle
|
51
51
|
else
|
52
52
|
@query.order("#{@resource.model_class.table_name}.#{@index_params[:sort_by]} #{@index_params[:sort_direction]}")
|
53
53
|
end
|
@@ -313,8 +313,20 @@ module Avo
|
|
313
313
|
@index_params[:sort_direction] = params[:sort_direction] || :desc
|
314
314
|
|
315
315
|
# View types
|
316
|
-
|
317
|
-
@index_params[:available_view_types] =
|
316
|
+
available_view_types = @resource.available_view_types
|
317
|
+
@index_params[:available_view_types] = available_view_types
|
318
|
+
|
319
|
+
@index_params[:view_type] = if params[:view_type].present?
|
320
|
+
params[:view_type]
|
321
|
+
elsif available_view_types.size == 1
|
322
|
+
available_view_types.first
|
323
|
+
else
|
324
|
+
@resource.default_view_type || Avo.configuration.default_view_type
|
325
|
+
end
|
326
|
+
|
327
|
+
if available_view_types.exclude? @index_params[:view_type].to_sym
|
328
|
+
raise "View type '#{@index_params[:view_type]}' is unavailable for #{@resource.class}."
|
329
|
+
end
|
318
330
|
end
|
319
331
|
|
320
332
|
def set_filters
|
@@ -14,7 +14,7 @@ module Avo
|
|
14
14
|
redirect_to computed_path
|
15
15
|
elsif !Rails.env.development?
|
16
16
|
@page_title = "Get started"
|
17
|
-
resource = Avo::
|
17
|
+
resource = Avo::Current.app.resource_manager.all.min_by { |resource| resource.model_key }
|
18
18
|
redirect_to resources_path(resource: resource)
|
19
19
|
end
|
20
20
|
end
|