avo 3.0.0.pre12 → 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/controllers/avo/actions_controller.rb +11 -1
- data/app/controllers/avo/associations_controller.rb +1 -1
- data/app/controllers/avo/base_controller.rb +14 -2
- 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/base_action.rb +8 -1
- data/lib/avo/base_resource.rb +73 -102
- data/lib/avo/concerns/filters_session_handler.rb +0 -1
- 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/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 +4 -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>
|
@@ -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
|
|
@@ -113,6 +113,16 @@ module Avo
|
|
113
113
|
)
|
114
114
|
end
|
115
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
|
+
|
116
126
|
def flash_messages(messages)
|
117
127
|
messages.each do |message|
|
118
128
|
flash[message[:type]] = message[:body]
|
@@ -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
|
@@ -37,11 +37,11 @@ module Avo
|
|
37
37
|
query = Avo::ExecutionContext.new(
|
38
38
|
target: resource.search_query,
|
39
39
|
params: params,
|
40
|
-
query: resource.class.
|
40
|
+
query: resource.class.query_scope
|
41
41
|
).handle
|
42
42
|
|
43
43
|
# Get the count
|
44
|
-
results_count = query.reselect(
|
44
|
+
results_count = query.reselect(resource.model_class.primary_key).count
|
45
45
|
|
46
46
|
# Get the results
|
47
47
|
query = query.limit(8)
|
@@ -58,7 +58,7 @@ module Avo
|
|
58
58
|
|
59
59
|
result_object = {
|
60
60
|
header: header,
|
61
|
-
help: resource.
|
61
|
+
help: resource.fetch_search(:help) || "",
|
62
62
|
results: results,
|
63
63
|
count: results.count
|
64
64
|
}
|
@@ -112,21 +112,17 @@ module Avo
|
|
112
112
|
# resource = avo_resource.dup.hydrate(record: record).hydrate_fields
|
113
113
|
resource = avo_resource.dup.hydrate(record: record)
|
114
114
|
|
115
|
-
fetch_result_information record, resource
|
115
|
+
fetch_result_information record, resource, resource.fetch_search(:item)
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
119
|
private
|
120
120
|
|
121
|
-
def fetch_result_information(record, resource)
|
121
|
+
def fetch_result_information(record, resource, item)
|
122
122
|
{
|
123
123
|
_id: record.id,
|
124
|
-
_label: resource.
|
125
|
-
_url:
|
126
|
-
target: resource.search_result_path || resource.record_path,
|
127
|
-
resource: resource,
|
128
|
-
record: record
|
129
|
-
).handle,
|
124
|
+
_label: item&.dig(:title) || resource.record_title,
|
125
|
+
_url: resource.fetch_search(:result_path) || resource.record_path
|
130
126
|
}
|
131
127
|
end
|
132
128
|
|
data/app/javascript/js/controllers/fields/{simple_mde_controller.js → easy_mde_controller.js}
RENAMED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
2
|
-
import
|
2
|
+
import EasyMDE from 'easymde'
|
3
3
|
|
4
4
|
export default class extends Controller {
|
5
5
|
static targets = ['element']
|
@@ -27,9 +27,9 @@ export default class extends Controller {
|
|
27
27
|
options.status = false
|
28
28
|
}
|
29
29
|
|
30
|
-
const
|
30
|
+
const easyMde = new EasyMDE(options)
|
31
31
|
if (this.view === 'show') {
|
32
|
-
|
32
|
+
easyMde.codemirror.options.readOnly = true
|
33
33
|
}
|
34
34
|
}
|
35
35
|
}
|
@@ -211,7 +211,9 @@ export default class extends Controller {
|
|
211
211
|
searchUrl(query) {
|
212
212
|
const url = URI()
|
213
213
|
|
214
|
-
return url.segment([window.Avo.configuration.root_path, ...this.searchSegments()])
|
214
|
+
return url.segment([window.Avo.configuration.root_path, ...this.searchSegments()])
|
215
|
+
.search(this.searchParams(encodeURIComponent(query)))
|
216
|
+
.readable().toString()
|
215
217
|
}
|
216
218
|
|
217
219
|
searchSegments() {
|