avo 2.5.2.pre.2 → 2.5.2.pre.3
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 +0 -2
- data/Gemfile.lock +1 -4
- data/app/assets/builds/avo.css +222 -812
- data/app/assets/builds/avo.js +123 -212
- data/app/assets/builds/avo.js.map +3 -3
- data/app/assets/stylesheets/avo.css +33 -3
- data/app/assets/stylesheets/css/search.css +1 -1
- data/app/assets/svgs/heroicons/solid/user-remove.svg +1 -1
- data/app/components/avo/actions_component.html.erb +2 -1
- data/app/components/avo/alert_component.html.erb +1 -1
- data/app/components/avo/alert_component.rb +24 -5
- data/app/components/avo/button_component.rb +2 -0
- data/app/components/avo/filters_component.html.erb +1 -1
- data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
- data/app/components/avo/index/grid_cover_empty_state_component.html.erb +1 -1
- data/app/components/avo/index/resource_table_component.html.erb +1 -1
- data/app/components/avo/panel_component.html.erb +3 -3
- data/app/components/avo/panel_component.rb +1 -1
- data/app/components/avo/resource_component.rb +50 -0
- data/app/components/avo/sidebar/heading_component.html.erb +1 -1
- data/app/components/avo/sidebar/link_component.rb +1 -1
- data/app/components/avo/sidebar_component.html.erb +5 -13
- data/app/components/avo/sidebar_profile_component.html.erb +1 -1
- data/app/components/avo/views/resource_edit_component.html.erb +28 -3
- data/app/components/avo/views/resource_edit_component.rb +4 -6
- data/app/components/avo/views/resource_index_component.html.erb +15 -7
- data/app/components/avo/views/resource_new_component.html.erb +8 -2
- data/app/components/avo/views/resource_show_component.html.erb +15 -5
- data/app/components/avo/views/resource_show_component.rb +0 -45
- data/app/controllers/avo/actions_controller.rb +23 -8
- data/app/controllers/avo/associations_controller.rb +1 -1
- data/app/controllers/avo/base_controller.rb +25 -16
- data/app/helpers/avo/application_helper.rb +1 -1
- data/app/javascript/js/application.js +1 -1
- data/app/javascript/js/controllers/fields/key_value_controller.js +1 -1
- data/app/javascript/js/controllers/filter_controller.js +4 -1
- data/app/javascript/js/controllers.js +0 -4
- data/app/views/avo/actions/show.html.erb +5 -2
- data/app/views/avo/partials/_logo.html.erb +1 -1
- data/app/views/avo/partials/_navbar.html.erb +12 -6
- data/app/views/avo/private/_links_and_buttons.html.erb +1 -1
- data/app/views/layouts/avo/application.html.erb +47 -53
- data/db/factories.rb +0 -2
- data/lib/avo/base_action.rb +24 -6
- data/lib/avo/base_resource.rb +0 -6
- data/lib/avo/engine.rb +1 -1
- data/lib/avo/fields/base_field.rb +1 -2
- data/lib/avo/fields/has_and_belongs_to_many_field.rb +2 -2
- data/lib/avo/fields/has_many_field.rb +2 -2
- data/lib/avo/fields/has_one_field.rb +2 -2
- data/lib/avo/licensing/pro_license.rb +1 -2
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/locales/avo.en.yml +0 -4
- data/public/avo-assets/avo.css +214 -812
- data/public/avo-assets/avo.js +123 -212
- data/public/avo-assets/avo.js.map +3 -3
- metadata +2 -19
- data/app/assets/stylesheets/css/alerts.css +0 -35
- data/app/assets/stylesheets/css/tags.css +0 -16
- data/app/components/avo/fields/tags_field/edit_component.html.erb +0 -27
- data/app/components/avo/fields/tags_field/edit_component.rb +0 -4
- data/app/components/avo/fields/tags_field/index_component.html.erb +0 -14
- data/app/components/avo/fields/tags_field/index_component.rb +0 -7
- data/app/components/avo/fields/tags_field/show_component.html.erb +0 -7
- data/app/components/avo/fields/tags_field/show_component.rb +0 -11
- data/app/components/avo/fields/tags_field/tag_component.html.erb +0 -9
- data/app/components/avo/fields/tags_field/tag_component.rb +0 -11
- data/app/javascript/js/controllers/alerts_controller.js +0 -26
- data/app/javascript/js/controllers/base_controller.js +0 -22
- data/app/javascript/js/controllers/fields/tags_field_controller.js +0 -86
- data/app/javascript/js/controllers/fields/tags_field_helpers.js +0 -47
- data/lib/avo/concerns/handles_field_args.rb +0 -36
- data/lib/avo/fields/tags_field.rb +0 -82
- data/lib/avo/hosts/record_host.rb +0 -7
@@ -4,7 +4,6 @@
|
|
4
4
|
@import './../../../node_modules/trix/dist/trix.css';
|
5
5
|
@import './../../../node_modules/flatpickr/dist/flatpickr.css';
|
6
6
|
@import './../../../node_modules/@algolia/autocomplete-theme-classic/dist/theme.css';
|
7
|
-
@import './../../../node_modules/@yaireo/tagify/dist/tagify.css';
|
8
7
|
|
9
8
|
@import 'tailwindcss/base';
|
10
9
|
|
@@ -12,14 +11,12 @@
|
|
12
11
|
@import './css/buttons.css';
|
13
12
|
@import './css/typography.css';
|
14
13
|
@import './css/tooltips.css';
|
15
|
-
@import './css/alerts.css';
|
16
14
|
@import './css/loader.css';
|
17
15
|
@import './css/pagination.css';
|
18
16
|
@import './css/breadcrumbs.css';
|
19
17
|
@import './css/search.css';
|
20
18
|
@import './css/active-storage.css';
|
21
19
|
@import './css/spinner.css';
|
22
|
-
@import './css/tags.css';
|
23
20
|
|
24
21
|
@import './css/components/status.css';
|
25
22
|
@import './css/components/code.css';
|
@@ -91,3 +88,36 @@ trix-editor {
|
|
91
88
|
max-height: 320px !important;
|
92
89
|
overflow-y: auto;
|
93
90
|
}
|
91
|
+
|
92
|
+
.scroll-shadows {
|
93
|
+
background:
|
94
|
+
/* Shadow Cover TOP */
|
95
|
+
linear-gradient(
|
96
|
+
#F6F6F7 30%,
|
97
|
+
#F6F6F7
|
98
|
+
) center top,
|
99
|
+
|
100
|
+
/* Shadow Cover BOTTOM */
|
101
|
+
linear-gradient(
|
102
|
+
#F6F6F7,
|
103
|
+
#F6F6F7 70%
|
104
|
+
) center bottom,
|
105
|
+
|
106
|
+
/* Shadow TOP */
|
107
|
+
radial-gradient(
|
108
|
+
farthest-side at 50% 0,
|
109
|
+
rgba(0, 0, 0, 0.2),
|
110
|
+
rgba(0, 0, 0, 0)
|
111
|
+
) center top,
|
112
|
+
|
113
|
+
/* Shadow BOTTOM */
|
114
|
+
radial-gradient(
|
115
|
+
farthest-side at 50% 100%,
|
116
|
+
rgba(0, 0, 0, 0.2),
|
117
|
+
rgba(0, 0, 0, 0)
|
118
|
+
) center bottom;
|
119
|
+
|
120
|
+
background-repeat: no-repeat;
|
121
|
+
background-size: 100% 34px, 100% 34px, 100% 14px, 100% 14px;
|
122
|
+
background-attachment: local, local, scroll, scroll;
|
123
|
+
}
|
@@ -1,3 +1,3 @@
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
1
|
+
or<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
2
2
|
<path d="M11 6a3 3 0 11-6 0 3 3 0 016 0zM14 17a6 6 0 00-12 0h12zM13 8a1 1 0 100 2h4a1 1 0 100-2h-4z"/>
|
3
3
|
</svg>
|
@@ -3,7 +3,8 @@
|
|
3
3
|
data-actions-picker-enabled-class="text-black hover:bg-blue-500 hover:text-white"
|
4
4
|
data-actions-picker-disabled-class="cursor-wait text-gray-500"
|
5
5
|
>
|
6
|
-
<%= a_button style: :
|
6
|
+
<%= a_button style: :outline,
|
7
|
+
color: :primary,
|
7
8
|
class: "focus:outline-none",
|
8
9
|
icon: 'arrow-circle-right',
|
9
10
|
icon_class: 'transform rotate-90',
|
@@ -13,7 +13,7 @@
|
|
13
13
|
<%== message %>
|
14
14
|
</p>
|
15
15
|
</div>
|
16
|
-
<div class="ml-4 flex-shrink-0 flex">
|
16
|
+
<div class="ml-4 flex-shrink-0 flex items-center">
|
17
17
|
<button data-action="alert#close" class="inline-flex text-white focus:outline-none focus:text-gray-300 transition ease-in-out duration-150">
|
18
18
|
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
19
19
|
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
|
@@ -12,7 +12,10 @@ class Avo::AlertComponent < ViewComponent::Base
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def icon
|
15
|
-
return "x-circle" if is_error?
|
15
|
+
return "heroicons/solid/x-circle" if is_error?
|
16
|
+
return "heroicons/solid/exclamation" if is_warning?
|
17
|
+
return "heroicons/solid/exclamation-circle" if is_info?
|
18
|
+
return "heroicons/solid/check-circle" if is_success?
|
16
19
|
|
17
20
|
"check-circle"
|
18
21
|
end
|
@@ -21,15 +24,31 @@ class Avo::AlertComponent < ViewComponent::Base
|
|
21
24
|
result = "max-w-lg w-full shadow-lg rounded px-4 py-3 rounded relative border text-white pointer-events-auto"
|
22
25
|
|
23
26
|
result += if is_error?
|
24
|
-
" bg-red-400 border-red-
|
25
|
-
|
26
|
-
" bg-green-
|
27
|
+
" bg-red-400 border-red-600"
|
28
|
+
elsif is_success?
|
29
|
+
" bg-green-500 border-green-600"
|
30
|
+
elsif is_warning?
|
31
|
+
" bg-orange-400 border-orange-600"
|
32
|
+
elsif is_info?
|
33
|
+
" bg-blue-400 border-blue-600"
|
27
34
|
end
|
28
35
|
|
29
36
|
result
|
30
37
|
end
|
31
38
|
|
32
39
|
def is_error?
|
33
|
-
type.to_sym == :error
|
40
|
+
type.to_sym == :error || type.to_sym == :alert
|
41
|
+
end
|
42
|
+
|
43
|
+
def is_success?
|
44
|
+
type.to_sym == :success
|
45
|
+
end
|
46
|
+
|
47
|
+
def is_info?
|
48
|
+
type.to_sym == :notice || type.to_sym == :info
|
49
|
+
end
|
50
|
+
|
51
|
+
def is_warning?
|
52
|
+
type.to_sym == :warning
|
34
53
|
end
|
35
54
|
end
|
@@ -117,6 +117,8 @@ class Avo::ButtonComponent < ViewComponent::Base
|
|
117
117
|
" bg-primary-500 text-white border-primary-500 hover:bg-primary-600 hover:border-primary-600 active:border-primary-700 active:outline-primary-700 active:bg-primary-600"
|
118
118
|
when :outline
|
119
119
|
" bg-white text-#{@color}-500 border-#{@color}-500 hover:bg-#{@color}-100 active:bg-#{@color}-100 active:border-#{@color}-500 active:outline-#{@color}-500"
|
120
|
+
when :text
|
121
|
+
" text-#{@color}-500 active:outline-#{@color}-500 border-none hover:bg-gray-100"
|
120
122
|
else
|
121
123
|
""
|
122
124
|
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
<% end %>
|
15
15
|
<% end %>
|
16
16
|
<div
|
17
|
-
class="absolute block inset-auto sm:right-0 top-full bg-white min-w-[300px] mt-2 z-20 shadow-modal rounded divide-y divide-gray-300 <%= 'hidden' unless params[:keep_filters_panel_open] %>"
|
17
|
+
class="absolute block inset-auto sm:right-0 top-full bg-white min-w-[300px] mt-2 z-20 shadow-modal rounded divide-y divide-gray-300 <%= 'hidden' unless params[:keep_filters_panel_open] == '1' %>"
|
18
18
|
data-toggle-panel-target="panel"
|
19
19
|
>
|
20
20
|
<% @filters.each do |filter| %>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<td class="min-h-[3rem] px-3 leading-tight whitespace-nowrap h-full text-slate-800 <%= classes %>" data-field-id="<%= @field.id %>" data-field-type="<%= @field.type %>">
|
1
|
+
<td class="min-h-[3rem] px-3 leading-tight whitespace-nowrap h-full text-slate-800 text-sm <%= classes %>" data-field-id="<%= @field.id %>" data-field-type="<%= @field.type %>">
|
2
2
|
<% if @field.value.blank? && @dash_if_blank %>
|
3
3
|
—
|
4
4
|
<% else %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div class="w-full ">
|
2
|
-
<table class="w-full px-4 bg-white" data-resource-name='<%= @resource.model_key %>' data-controller='item-select-all'>
|
2
|
+
<table class="w-full px-4 bg-white rounded" data-resource-name='<%= @resource.model_key %>' data-controller='item-select-all'>
|
3
3
|
<%= render partial: 'avo/partials/table_header', locals: {fields: @resource.get_fields(reflection: @reflection)} %>
|
4
4
|
<tbody class="divide-y">
|
5
5
|
<% @resources.each_with_index do |resource, index| %>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<div <%== data_attributes %>>
|
2
2
|
<% if render_header? %>
|
3
|
-
<div class="
|
4
|
-
<div class="overflow-hidden
|
3
|
+
<div class="flex-1 flex flex-col xl:flex-row justify-between mb-4">
|
4
|
+
<div class="overflow-hidden flex flex-col">
|
5
5
|
<% if display_breadcrumbs? %>
|
6
6
|
<div class="breadcrumbs truncate mb-2">
|
7
7
|
<%= helpers.render_breadcrumbs(separator: helpers.svg('chevron-right', class: 'inline-block h-3 stroke-current relative top-[-1px] ml-1' )) if Avo.configuration.display_breadcrumbs %>
|
@@ -13,7 +13,7 @@
|
|
13
13
|
</div>
|
14
14
|
|
15
15
|
<% if description.present? %>
|
16
|
-
<div class="text-
|
16
|
+
<div class="text-sm tracking-normal font-medium text-gray-600" data-target="description">
|
17
17
|
<%== description %>
|
18
18
|
</div>
|
19
19
|
<% end %>
|
@@ -11,6 +11,26 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
11
11
|
@resource.authorization.authorize_action(:destroy, raise_exception: false)
|
12
12
|
end
|
13
13
|
|
14
|
+
def can_detach?
|
15
|
+
authorize_association_for("detach")
|
16
|
+
end
|
17
|
+
|
18
|
+
def can_see_the_edit_button?
|
19
|
+
@resource.authorization.authorize_action(:edit, raise_exception: false)
|
20
|
+
end
|
21
|
+
|
22
|
+
def can_see_the_destroy_button?
|
23
|
+
@resource.authorization.authorize_action(:destroy, raise_exception: false)
|
24
|
+
end
|
25
|
+
|
26
|
+
def detach_path
|
27
|
+
helpers.resource_detach_path(params[:resource_name], params[:id], @reflection.name.to_s, @resource.model.id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy_path
|
31
|
+
helpers.resource_path(model: @resource.model, resource: @resource)
|
32
|
+
end
|
33
|
+
|
14
34
|
def authorize_association_for(policy_method)
|
15
35
|
association_policy = true
|
16
36
|
|
@@ -30,4 +50,34 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
30
50
|
|
31
51
|
association_policy
|
32
52
|
end
|
53
|
+
|
54
|
+
def split_panel_fields
|
55
|
+
initialize_panels
|
56
|
+
@resource.get_fields.each do |field|
|
57
|
+
case field.class.to_s
|
58
|
+
when "Avo::Fields::HasOneField"
|
59
|
+
@has_one_panels << field
|
60
|
+
when "Avo::Fields::HasManyField"
|
61
|
+
@has_many_panels << field
|
62
|
+
when "Avo::Fields::HasAndBelongsToManyField"
|
63
|
+
@has_as_belongs_to_many_panels << field
|
64
|
+
else
|
65
|
+
@fields_by_panel[field.panel_name] ||= []
|
66
|
+
@fields_by_panel[field.panel_name] << field
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def initialize_panels
|
74
|
+
@fields_by_panel = {}
|
75
|
+
@has_one_panels = []
|
76
|
+
@has_many_panels = []
|
77
|
+
@has_as_belongs_to_many_panels = []
|
78
|
+
end
|
79
|
+
|
80
|
+
def via_resource?
|
81
|
+
params[:via_resource_class].present? && params[:via_resource_id].present?
|
82
|
+
end
|
33
83
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="flex justify-between
|
1
|
+
<div class="flex justify-between px-6 py-2 text-gray-500">
|
2
2
|
<div class="flex items-center text-sm uppercase font-semibold leading-none space-x-1">
|
3
3
|
<span class="min-w-[20px]"><%= icon %></span> <span><%= label %></span>
|
4
4
|
</div>
|
@@ -23,6 +23,6 @@ class Avo::Sidebar::LinkComponent < ViewComponent::Base
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def classes
|
26
|
-
"px-4 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-
|
26
|
+
"px-4 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-100"
|
27
27
|
end
|
28
28
|
end
|
@@ -1,24 +1,16 @@
|
|
1
1
|
<div
|
2
|
-
class="fixed z-[60] application-sidebar hidden lg:flex
|
2
|
+
class="fixed z-[60] t-0 application-sidebar hidden lg:flex flex-1 border-r lg:border-none bg-none min-w-[16rem] h-[calc(100vh-4rem)] bg-gray-50 lg:bg-transparent <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>"
|
3
3
|
data-mobile-target="sidebar"
|
4
4
|
>
|
5
5
|
<div class="flex flex-col w-full h-full">
|
6
|
-
<div class="flex justify-between">
|
7
|
-
<%= render partial: "avo/partials/logo" %>
|
8
|
-
<div class="flex items-center mr-4">
|
9
|
-
<%= helpers.a_button class: "lg:hidden", icon: 'menu-back', data: { action: 'click->mobile#toggleSidebar' } %>
|
10
|
-
</div>
|
11
|
-
</div>
|
12
|
-
<div class="flex-1 flex flex-col justify-between overflow-auto mt-3">
|
6
|
+
<div class="flex-1 flex flex-col justify-between overflow-auto h-full pt-3 scroll-shadows">
|
13
7
|
<div class="space-y-6 mb-4">
|
14
8
|
<%= 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
9
|
|
16
10
|
<% if Avo::App.has_main_menu? %>
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
<% end %>
|
21
|
-
</div>
|
11
|
+
<% Avo::App.main_menu.items.each do |item| %>
|
12
|
+
<%= render Avo::Sidebar::ItemSwitcherComponent.new item: item %>
|
13
|
+
<% end %>
|
22
14
|
<% else %>
|
23
15
|
|
24
16
|
<% if dashboards.present? %>
|
@@ -1,4 +1,6 @@
|
|
1
|
-
<div data-model-id="<%= @resource.model.id %>"
|
1
|
+
<div data-model-id="<%= @resource.model.id %>"
|
2
|
+
class="space-y-8"
|
3
|
+
>
|
2
4
|
<% @resource.panels.each do |resource_panel| %>
|
3
5
|
<%= form_with model: @resource.model,
|
4
6
|
scope: @resource.form_scope,
|
@@ -9,11 +11,17 @@
|
|
9
11
|
<%= render Avo::ReferrerParamsComponent.new back_path: back_path %>
|
10
12
|
<%= render Avo::PanelComponent.new(title: resource_panel[:name], description: @resource.resource_description, display_breadcrumbs: true) do |c| %>
|
11
13
|
<% c.tools do %>
|
12
|
-
<%= a_link back_path,
|
14
|
+
<%= a_link back_path,
|
15
|
+
style: :text,
|
16
|
+
icon: 'arrow-left' do %>
|
13
17
|
<%= t('avo.cancel').capitalize %>
|
14
18
|
<% end %>
|
15
19
|
<% if can_see_the_save_button? %>
|
16
|
-
<%= a_button color: :
|
20
|
+
<%= a_button color: :primary,
|
21
|
+
style: :primary,
|
22
|
+
loading: true,
|
23
|
+
type: :submit,
|
24
|
+
icon: 'save' do %>
|
17
25
|
<%= t('avo.save').capitalize %>
|
18
26
|
<% end %>
|
19
27
|
<% end %>
|
@@ -40,4 +48,21 @@
|
|
40
48
|
<% end %>
|
41
49
|
<% end %>
|
42
50
|
<% end %>
|
51
|
+
<% if @reflection.blank? %>
|
52
|
+
<% if has_one_panels.present? %>
|
53
|
+
<% has_one_panels.each_with_index do |field, index| %>
|
54
|
+
<%= render field.component_for_view(:show).new(field: field, resource: @resource, index: index) %>
|
55
|
+
<% end %>
|
56
|
+
<% end %>
|
57
|
+
<% if has_many_panels.present? %>
|
58
|
+
<% has_many_panels.each_with_index do |field, index| %>
|
59
|
+
<%= render field.component_for_view(:show).new(field: field, resource: @resource, index: index) %>
|
60
|
+
<% end %>
|
61
|
+
<% end %>
|
62
|
+
<% if has_as_belongs_to_many_panels.present? %>
|
63
|
+
<% has_as_belongs_to_many_panels.each_with_index do |field, index| %>
|
64
|
+
<%= render field.component_for_view(:show).new(field: field, resource: @resource, index: index) %>
|
65
|
+
<% end %>
|
66
|
+
<% end %>
|
67
|
+
<% end %>
|
43
68
|
</div>
|
@@ -4,8 +4,12 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
|
|
4
4
|
include Avo::ResourcesHelper
|
5
5
|
include Avo::ApplicationHelper
|
6
6
|
|
7
|
+
attr_reader :fields_by_panel, :has_one_panels, :has_many_panels, :has_as_belongs_to_many_panels
|
8
|
+
|
7
9
|
def initialize(resource: nil)
|
8
10
|
@resource = resource
|
11
|
+
|
12
|
+
split_panel_fields
|
9
13
|
end
|
10
14
|
|
11
15
|
def back_path
|
@@ -21,10 +25,4 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
|
|
21
25
|
def can_see_the_save_button?
|
22
26
|
@resource.authorization.authorize_action :edit, raise_exception: false
|
23
27
|
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def via_resource?
|
28
|
-
params[:via_resource_class].present? && params[:via_resource_id].present?
|
29
|
-
end
|
30
28
|
end
|
@@ -1,19 +1,28 @@
|
|
1
1
|
<div>
|
2
2
|
<%= render Avo::PanelComponent.new(title: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
|
3
3
|
<% c.tools do %>
|
4
|
+
<% if can_attach? %>
|
5
|
+
<%= a_link attach_path,
|
6
|
+
icon: 'heroicons/outline/link',
|
7
|
+
color: :primary,
|
8
|
+
style: :text,
|
9
|
+
'data-turbo-frame': 'attach_modal',
|
10
|
+
'data-target': 'attach' do %>
|
11
|
+
<%= t('avo.attach_item', item: singular_resource_name).capitalize %>
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
4
14
|
<% if can_see_the_actions_button? %>
|
5
15
|
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
|
6
16
|
<% end %>
|
7
17
|
<% if can_see_the_create_button? %>
|
8
|
-
<%= a_link create_path,
|
18
|
+
<%= a_link create_path,
|
19
|
+
icon: 'heroicons/outline/plus',
|
20
|
+
'data-target': 'create',
|
21
|
+
style: :primary,
|
22
|
+
color: :primary do %>
|
9
23
|
<%= t('avo.create_new_item', item: singular_resource_name.downcase ) %>
|
10
24
|
<% end %>
|
11
25
|
<% end %>
|
12
|
-
<% if can_attach? %>
|
13
|
-
<%= a_link attach_path, icon: 'heroicons/outline/link', color: :primary, 'data-turbo-frame': 'attach_modal', 'data-target': 'attach' do %>
|
14
|
-
<%= t('avo.attach_item', item: singular_resource_name).capitalize %>
|
15
|
-
<% end %>
|
16
|
-
<% end %>
|
17
26
|
<% end %>
|
18
27
|
<% c.body do %>
|
19
28
|
<div class="flex flex-col xs:flex-row xs:justify-between space-y-2 xs:space-y-0 py-4 <%= 'hidden' if @resource.search_query.nil? && @filters.empty? && available_view_types.count <= 1 %>"
|
@@ -55,7 +64,6 @@
|
|
55
64
|
</div>
|
56
65
|
<% end %>
|
57
66
|
<% end %>
|
58
|
-
|
59
67
|
<% if view_type.to_sym == :grid %>
|
60
68
|
<%= render Avo::Index::ResourceGridComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model) %>
|
61
69
|
<div class="mt-14">
|
@@ -14,11 +14,17 @@
|
|
14
14
|
<%= render Avo::PanelComponent.new(title: resource_panel[:name], description: @resource.resource_description, display_breadcrumbs: true) do |c| %>
|
15
15
|
<% c.tools do %>
|
16
16
|
<div class="flex justify-end space-x-2">
|
17
|
-
<%= a_link back_path,
|
17
|
+
<%= a_link back_path,
|
18
|
+
style: :text,
|
19
|
+
icon: 'arrow-left' do %>
|
18
20
|
<%= t('avo.cancel').capitalize %>
|
19
21
|
<% end %>
|
20
22
|
<% if can_see_the_save_button? %>
|
21
|
-
<%= a_button color:
|
23
|
+
<%= a_button color: :primary,
|
24
|
+
style: :primary,
|
25
|
+
loading: true,
|
26
|
+
type: :submit,
|
27
|
+
icon: 'save' do %>
|
22
28
|
<%= t('avo.save').capitalize %>
|
23
29
|
<% end %>
|
24
30
|
<% end %>
|
@@ -8,32 +8,38 @@
|
|
8
8
|
<% c.tools do %>
|
9
9
|
<% if resource_panel[:name] == @resource.default_panel_name %>
|
10
10
|
<% if @reflection.present? && @resource.model.present? %>
|
11
|
-
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
|
12
11
|
<% if can_detach? %>
|
13
12
|
<%= a_button url: detach_path,
|
14
13
|
icon: 'detach',
|
15
14
|
method: :delete,
|
16
15
|
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
16
|
+
style: :text,
|
17
17
|
data: {
|
18
18
|
confirm: "Are you sure you want to detach this #{@reflection.name.to_s}."
|
19
19
|
} do %>
|
20
20
|
<%= t('avo.detach_item', item: @reflection.name.to_s).capitalize %>
|
21
21
|
<% end %>
|
22
|
+
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
|
22
23
|
<% end %>
|
23
24
|
<% if can_see_the_edit_button? %>
|
24
|
-
<%= a_link edit_path,
|
25
|
+
<%= a_link edit_path,
|
26
|
+
color: :primary,
|
27
|
+
style: :primary,
|
28
|
+
icon: 'edit' do %>
|
25
29
|
<%= t('avo.edit').capitalize %>
|
26
30
|
<% end %>
|
27
31
|
<% end %>
|
28
32
|
<% else %>
|
29
|
-
<%= a_link back_path,
|
33
|
+
<%= a_link back_path,
|
34
|
+
style: :text,
|
35
|
+
icon: 'arrow-left' do %>
|
30
36
|
<%= t('avo.go_back') %>
|
31
37
|
<% end %>
|
32
|
-
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
|
33
38
|
<% if can_see_the_destroy_button? %>
|
34
39
|
<%= a_button url: helpers.resource_path(model: @resource.model, resource: @resource),
|
35
40
|
method: :delete,
|
36
41
|
local: true,
|
42
|
+
style: :text,
|
37
43
|
title: t('avo.delete_item', item: @resource.model.model_name.name.downcase).capitalize,
|
38
44
|
loading: true,
|
39
45
|
confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
|
@@ -48,8 +54,12 @@
|
|
48
54
|
<%= t('avo.delete').capitalize %>
|
49
55
|
<% end %>
|
50
56
|
<% end %>
|
57
|
+
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
|
51
58
|
<% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
|
52
|
-
<%= a_link edit_path,
|
59
|
+
<%= a_link edit_path,
|
60
|
+
color: :primary,
|
61
|
+
style: :primary,
|
62
|
+
icon: 'edit' do %>
|
53
63
|
<%= t('avo.edit').capitalize %>
|
54
64
|
<% end %>
|
55
65
|
<% end %>
|
@@ -44,53 +44,8 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
|
|
44
44
|
helpers.edit_resource_path(model: @resource.model, resource: @resource, **args)
|
45
45
|
end
|
46
46
|
|
47
|
-
def detach_path
|
48
|
-
helpers.resource_detach_path(params[:resource_name], params[:id], @reflection.name.to_s, @resource.model.id)
|
49
|
-
end
|
50
|
-
|
51
|
-
def destroy_path
|
52
|
-
helpers.resource_path(model: @resource.model, resource: @resource)
|
53
|
-
end
|
54
|
-
|
55
|
-
def can_detach?
|
56
|
-
authorize_association_for("detach")
|
57
|
-
end
|
58
|
-
|
59
|
-
def can_see_the_edit_button?
|
60
|
-
@resource.authorization.authorize_action(:edit, raise_exception: false)
|
61
|
-
end
|
62
|
-
|
63
|
-
def can_see_the_destroy_button?
|
64
|
-
@resource.authorization.authorize_action(:destroy, raise_exception: false)
|
65
|
-
end
|
66
|
-
|
67
47
|
private
|
68
48
|
|
69
|
-
def via_resource?
|
70
|
-
params[:via_resource_class].present? && params[:via_resource_id].present?
|
71
|
-
end
|
72
|
-
|
73
|
-
def split_panel_fields
|
74
|
-
@fields_by_panel = {}
|
75
|
-
@has_one_panels = []
|
76
|
-
@has_many_panels = []
|
77
|
-
@has_as_belongs_to_many_panels = []
|
78
|
-
|
79
|
-
@resource.get_fields.each do |field|
|
80
|
-
case field.class.to_s
|
81
|
-
when "Avo::Fields::HasOneField"
|
82
|
-
@has_one_panels << field
|
83
|
-
when "Avo::Fields::HasManyField"
|
84
|
-
@has_many_panels << field
|
85
|
-
when "Avo::Fields::HasAndBelongsToManyField"
|
86
|
-
@has_as_belongs_to_many_panels << field
|
87
|
-
else
|
88
|
-
@fields_by_panel[field.panel_name] ||= []
|
89
|
-
@fields_by_panel[field.panel_name] << field
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
49
|
# In development and test environments we shoudl show the invalid field errors
|
95
50
|
def should_display_invalid_fields_errors?
|
96
51
|
(Rails.env.development? || Rails.env.test?) && @resource.invalid_fields.present?
|
@@ -14,14 +14,12 @@ module Avo
|
|
14
14
|
resource_ids = action_params[:fields][:resource_ids].split(",")
|
15
15
|
models = @resource.class.find_scope.find resource_ids
|
16
16
|
|
17
|
-
fields = action_params[:fields].
|
18
|
-
key != "resource_ids"
|
19
|
-
end
|
17
|
+
fields = action_params[:fields].except("resource_ids")
|
20
18
|
|
21
19
|
args = {
|
22
20
|
fields: fields,
|
23
21
|
current_user: _current_user,
|
24
|
-
resource: resource
|
22
|
+
resource: resource
|
25
23
|
}
|
26
24
|
|
27
25
|
args[:models] = models unless @action.standalone
|
@@ -49,8 +47,7 @@ module Avo
|
|
49
47
|
|
50
48
|
def respond(response)
|
51
49
|
response[:type] ||= :reload
|
52
|
-
|
53
|
-
response[:message] ||= I18n.t("avo.action_ran_successfully")
|
50
|
+
messages = get_messages response
|
54
51
|
|
55
52
|
if response[:type] == :download
|
56
53
|
return send_data response[:path], filename: response[:filename]
|
@@ -58,6 +55,11 @@ module Avo
|
|
58
55
|
|
59
56
|
respond_to do |format|
|
60
57
|
format.html do
|
58
|
+
# Flash the messages collected from the action
|
59
|
+
messages.each do |message|
|
60
|
+
flash[message[:type]] = message[:body]
|
61
|
+
end
|
62
|
+
|
61
63
|
if response[:type] == :redirect
|
62
64
|
path = response[:path]
|
63
65
|
|
@@ -65,12 +67,25 @@ module Avo
|
|
65
67
|
path = instance_eval(&path)
|
66
68
|
end
|
67
69
|
|
68
|
-
redirect_to path
|
70
|
+
redirect_to path
|
69
71
|
elsif response[:type] == :reload
|
70
|
-
redirect_back fallback_location: resources_path(resource: @resource)
|
72
|
+
redirect_back fallback_location: resources_path(resource: @resource)
|
71
73
|
end
|
72
74
|
end
|
73
75
|
end
|
74
76
|
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def get_messages(response)
|
81
|
+
default_message = {
|
82
|
+
type: :info,
|
83
|
+
body: I18n.t("avo.action_ran_successfully")
|
84
|
+
}
|
85
|
+
|
86
|
+
return [default_message] if response[:messages].blank?
|
87
|
+
|
88
|
+
response[:messages]
|
89
|
+
end
|
75
90
|
end
|
76
91
|
end
|
@@ -65,7 +65,7 @@ module Avo
|
|
65
65
|
|
66
66
|
respond_to do |format|
|
67
67
|
if @model.save
|
68
|
-
format.html {
|
68
|
+
format.html { redirect_back fallback_location: resource_path(model: @model, resource: @resource), notice: t("avo.attachment_class_attached", attachment_class: @related_resource.name) }
|
69
69
|
else
|
70
70
|
format.html { render :new }
|
71
71
|
end
|