avo 2.11.2.pre.3 → 2.11.3.pre.1
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.css +1 -0
- data/app/assets/stylesheets/css/scrollbar.css +30 -0
- data/app/components/avo/actions_component.html.erb +3 -3
- data/app/components/avo/actions_component.rb +12 -3
- data/app/components/avo/button_component.rb +1 -3
- data/app/components/avo/paginator_component.html.erb +35 -33
- data/app/components/avo/paginator_component.rb +3 -1
- data/app/components/avo/panel_component.html.erb +1 -1
- data/app/components/avo/resource_component.rb +6 -4
- data/app/components/avo/sidebar_component.html.erb +1 -1
- data/app/components/avo/tab_switcher_component.html.erb +1 -1
- data/app/components/avo/views/resource_index_component.html.erb +3 -3
- data/app/components/avo/views/resource_show_component.html.erb +143 -52
- data/app/components/avo/views/resource_show_component.rb +1 -0
- data/app/controllers/avo/base_controller.rb +8 -7
- data/app/javascript/avo.js +1 -1
- data/app/javascript/js/controllers/fields/date_field_controller.js +7 -3
- data/app/views/avo/debug/report.html.erb +1 -0
- data/app/views/avo/private/design.html.erb +1 -1
- data/lib/avo/base_resource.rb +5 -1
- data/lib/avo/concerns/has_editable_controls.rb +34 -0
- data/lib/avo/fields/date_time_field.rb +2 -2
- data/lib/avo/fields/has_base_field.rb +2 -0
- data/lib/avo/licensing/pro_license.rb +1 -0
- data/lib/avo/resources/controls/action.rb +32 -0
- data/lib/avo/resources/controls/actions_list.rb +19 -0
- data/lib/avo/resources/controls/back_button.rb +13 -0
- data/lib/avo/resources/controls/base_control.rb +59 -0
- data/lib/avo/resources/controls/delete_button.rb +13 -0
- data/lib/avo/resources/controls/detach_button.rb +13 -0
- data/lib/avo/resources/controls/edit_button.rb +13 -0
- data/lib/avo/resources/controls/execution_context.rb +59 -0
- data/lib/avo/resources/controls/items_holder.rb +19 -0
- data/lib/avo/resources/controls/link_to.rb +27 -0
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/action.tt +1 -1
- data/lib/generators/avo/templates/resource_tools/partial.tt +1 -1
- data/lib/generators/avo/templates/standalone_action.tt +1 -1
- data/public/avo-assets/avo.css +602 -43
- data/public/avo-assets/avo.js +2 -2
- data/public/avo-assets/avo.js.map +2 -2
- metadata +14 -3
- data/lib/avo/concerns/has_model.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6322eef586c1cf132343d666fa513b2733699349d2945a86ddb2b37669cfcd1c
|
4
|
+
data.tar.gz: 5fb654449921d9fde5312adbeee074f96752445c34416ea4a6a22e6c5f9be9df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c9ee8afe73d49806a42032b5c3f2b8c49a05763d44048e44c55ab4831d30c475ad2792cb6ad11ce5bd8ce296202c20173dd8bf274b05c64f6ac60174835953b
|
7
|
+
data.tar.gz: f22c15ebaaee96768cd5c38c2935a513410a32a5e46729b22c4c8375c1b7a229b4e3e733572f3fe47207229bae4775ce3a5510c528a532759c81b8b2b0b39fc7
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
/* total width */
|
2
|
+
body.os-pc .mac-styled-scrollbar::-webkit-scrollbar {
|
3
|
+
background-color: none;
|
4
|
+
width: 0.5rem;
|
5
|
+
height: 0.5rem;
|
6
|
+
}
|
7
|
+
|
8
|
+
/* background of the scrollbar except button or resizer */
|
9
|
+
body.os-pc .mac-styled-scrollbar::-webkit-scrollbar-track {
|
10
|
+
background-color: none;
|
11
|
+
}
|
12
|
+
|
13
|
+
/* scrollbar itself */
|
14
|
+
body.os-pc .mac-styled-scrollbar::-webkit-scrollbar-thumb {
|
15
|
+
background-color: #babac0;
|
16
|
+
border-radius: 0.5rem;
|
17
|
+
}
|
18
|
+
|
19
|
+
/* set button(top and bottom of the scrollbar) */
|
20
|
+
body.os-pc .mac-styled-scrollbar::-webkit-scrollbar-button {
|
21
|
+
display:none;
|
22
|
+
}
|
23
|
+
/* hide by default */
|
24
|
+
body.os-pc .mac-styled-scrollbar::-webkit-scrollbar-thumb {
|
25
|
+
display:none
|
26
|
+
}
|
27
|
+
/* show on hover */
|
28
|
+
body.os-pc .mac-styled-scrollbar:hover::-webkit-scrollbar-thumb {
|
29
|
+
display:block
|
30
|
+
}
|
@@ -3,9 +3,9 @@
|
|
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: @style,
|
7
7
|
type: :button,
|
8
|
-
color:
|
8
|
+
color: @color,
|
9
9
|
class: "focus:outline-none",
|
10
10
|
icon: 'arrow-circle-right',
|
11
11
|
icon_class: 'transform rotate-90',
|
@@ -18,7 +18,7 @@
|
|
18
18
|
data-toggle-panel-target="panel"
|
19
19
|
>
|
20
20
|
<div class="w-full space divide-y">
|
21
|
-
<%
|
21
|
+
<% actions.each_with_index do |action, index| %>
|
22
22
|
<%= link_to action_path(action.param_id),
|
23
23
|
data: {
|
24
24
|
'turbo-frame': 'actions_show',
|
@@ -3,14 +3,23 @@
|
|
3
3
|
class Avo::ActionsComponent < ViewComponent::Base
|
4
4
|
include Avo::ApplicationHelper
|
5
5
|
|
6
|
-
def initialize(actions: [], resource: nil, view: nil)
|
7
|
-
@actions = actions
|
6
|
+
def initialize(actions: [], resource: nil, view: nil, exclude: [], style: :outline, color: :blue)
|
7
|
+
@actions = actions || []
|
8
8
|
@resource = resource
|
9
9
|
@view = view
|
10
|
+
@exclude = exclude
|
11
|
+
@color = color
|
12
|
+
@style = style
|
10
13
|
end
|
11
14
|
|
12
15
|
def render?
|
13
|
-
|
16
|
+
actions.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def actions
|
20
|
+
@actions.select do |action|
|
21
|
+
!action.class.in?(@exclude)
|
22
|
+
end
|
14
23
|
end
|
15
24
|
|
16
25
|
# When running an action for one record we should do it on a special path.
|
@@ -43,9 +43,7 @@ class Avo::ButtonComponent < ViewComponent::Base
|
|
43
43
|
classes = "button-component inline-flex flex-grow-0 items-center font-semibold leading-6 fill-current whitespace-nowrap transition duration-100 transform transition duration-100 cursor-pointer disabled:cursor-not-allowed disabled:opacity-70 border justify-center active:outline active:outline-1 #{@class}"
|
44
44
|
|
45
45
|
classes += " rounded" if @rounded.present?
|
46
|
-
|
47
46
|
classes += style_classes
|
48
|
-
|
49
47
|
classes += horizontal_padding_classes
|
50
48
|
classes += vertical_padding_classes
|
51
49
|
classes += text_size_classes
|
@@ -151,7 +149,7 @@ class Avo::ButtonComponent < ViewComponent::Base
|
|
151
149
|
def style_classes
|
152
150
|
case @style
|
153
151
|
when :primary
|
154
|
-
" bg-
|
152
|
+
" bg-#{@color}-500 text-white border-#{@color}-500 hover:bg-#{@color}-600 hover:border-#{@color}-600 active:border-#{@color}-700 active:outline-#{@color}-700 active:bg-#{@color}-600"
|
155
153
|
when :outline
|
156
154
|
" bg-white text-#{@color}-500 border-#{@color}-500 hover:bg-#{@color}-100 active:bg-#{@color}-100 active:border-#{@color}-500 active:outline-#{@color}-500"
|
157
155
|
when :text
|
@@ -7,43 +7,45 @@
|
|
7
7
|
|
8
8
|
per_page_options = per_page_options.sort.uniq
|
9
9
|
%>
|
10
|
-
|
11
|
-
<div class="flex-
|
12
|
-
<div>
|
13
|
-
<div
|
14
|
-
<div
|
15
|
-
<div
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
<%
|
28
|
-
|
29
|
-
|
30
|
-
|
10
|
+
<% unless @pagy.pages <= 1 && discreet_pagination %>
|
11
|
+
<div class="flex flex-col sm:flex-row items-center justify-between aborder-t aborder-slate-200 rounded-xl space-y-2 sm:space-y-0">
|
12
|
+
<div class="flex-2 sm:flex sm:items-center sm:justify-between">
|
13
|
+
<div>
|
14
|
+
<div class="text-sm leading-5 text-slate-600 flex items-center">
|
15
|
+
<div data-controller="per-page">
|
16
|
+
<div class="flex items-center">
|
17
|
+
<%= select_tag 'per_page',
|
18
|
+
options_for_select(per_page_options, index_params[:per_page]),
|
19
|
+
class: 'appearance-none inline-flex bg-white-100 disabled:bg-white-400 disabled:cursor-not-allowed focus:bg-white text-slate-700 disabled:text-slate-600 rounded-md py-1 px-2 leading-tight border border-slate-300 outline-none focus:border-slate-400 outline w-16 mr-1 text-sm',
|
20
|
+
data: {
|
21
|
+
'turbo-frame': turbo_frame,
|
22
|
+
'per-page-target': 'selector',
|
23
|
+
action: 'change->per-page#reload'
|
24
|
+
}
|
25
|
+
%> <%= t('avo.per_page').downcase %>
|
26
|
+
</div>
|
27
|
+
<% per_page_options.each do |option| %>
|
28
|
+
<% if parent_model.present? %>
|
29
|
+
<%= link_to "Change to #{option} items per page", helpers.related_resources_path(parent_model, parent_model, per_page: option, keep_query_params: true, page: 1), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
|
30
|
+
<% else %>
|
31
|
+
<%= link_to "Change to #{option} items per page", helpers.resources_path(resource: resource, per_page: option, keep_query_params: true, page: 1), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
|
32
|
+
<% end %>
|
31
33
|
<% end %>
|
32
|
-
|
34
|
+
</div>
|
33
35
|
</div>
|
34
36
|
</div>
|
35
37
|
</div>
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
<% end %>
|
38
|
+
<div class="flex">
|
39
|
+
<div class="flex-2 sm:flex sm:items-center sm:justify-between space-y-2 sm:space-y-0 text-center sm:text-left">
|
40
|
+
<% if @pagy.count > 0 %>
|
41
|
+
<div class="text-sm text-slate-600 mr-4"><%== helpers.pagy_info @pagy %></div>
|
42
|
+
<% end %>
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
<% if @pagy.pages > 1 %>
|
45
|
+
<%# @todo: add first & last page. make the first and last buttons rounded %>
|
46
|
+
<%== helpers.pagy_nav @pagy %>
|
47
|
+
<% end %>
|
48
|
+
</div>
|
47
49
|
</div>
|
48
50
|
</div>
|
49
|
-
|
51
|
+
<% end %>
|
@@ -6,12 +6,14 @@ class Avo::PaginatorComponent < ViewComponent::Base
|
|
6
6
|
attr_reader :index_params
|
7
7
|
attr_reader :resource
|
8
8
|
attr_reader :parent_model
|
9
|
+
attr_reader :discreet_pagination
|
9
10
|
|
10
|
-
def initialize(resource: nil, parent_model: nil, pagy: nil, turbo_frame: nil, index_params: nil)
|
11
|
+
def initialize(resource: nil, parent_model: nil, pagy: nil, turbo_frame: nil, index_params: nil, discreet_pagination: nil)
|
11
12
|
@pagy = pagy
|
12
13
|
@turbo_frame = turbo_frame
|
13
14
|
@index_params = index_params
|
14
15
|
@resource = resource
|
15
16
|
@parent_model = parent_model
|
17
|
+
@discreet_pagination = discreet_pagination
|
16
18
|
end
|
17
19
|
end
|
@@ -17,7 +17,7 @@
|
|
17
17
|
<% end %>
|
18
18
|
</div>
|
19
19
|
<% if tools.present? %>
|
20
|
-
<div class="flex-1 w-full flex flex-col sm:flex-row xl:justify-end sm:items-end
|
20
|
+
<div class="flex-1 w-full flex flex-wrap flex-col sm:flex-row xl:justify-end sm:items-end gap-2 mt-4 xl:mt-0" data-target="panel-controls">
|
21
21
|
<%= tools %>
|
22
22
|
</div>
|
23
23
|
<% end %>
|
@@ -22,6 +22,12 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
22
22
|
authorize_association_for("detach")
|
23
23
|
end
|
24
24
|
|
25
|
+
def detach_path
|
26
|
+
return "/" if @reflection.blank?
|
27
|
+
|
28
|
+
helpers.resource_detach_path(params[:resource_name], params[:id], @reflection.name.to_s, @resource.model.id)
|
29
|
+
end
|
30
|
+
|
25
31
|
def can_see_the_edit_button?
|
26
32
|
@resource.authorization.authorize_action(:edit, raise_exception: false)
|
27
33
|
end
|
@@ -30,10 +36,6 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
30
36
|
@resource.authorization.authorize_action(:destroy, raise_exception: false)
|
31
37
|
end
|
32
38
|
|
33
|
-
def detach_path
|
34
|
-
helpers.resource_detach_path(params[:resource_name], params[:id], @reflection.name.to_s, @resource.model.id)
|
35
|
-
end
|
36
|
-
|
37
39
|
def destroy_path
|
38
40
|
helpers.resource_path(model: @resource.model, resource: @resource)
|
39
41
|
end
|
@@ -9,7 +9,7 @@
|
|
9
9
|
data-transition-leave-end="transform opacity-0 -translate-x-full"
|
10
10
|
>
|
11
11
|
<div class="flex flex-col w-full h-full">
|
12
|
-
<div class="flex-1 flex flex-col justify-between overflow-auto h-full pt-3 scroll-shadows">
|
12
|
+
<div class="flex-1 flex flex-col justify-between overflow-auto h-full pt-3 scroll-shadows mac-styled-scrollbar">
|
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
|
|
@@ -49,7 +49,7 @@
|
|
49
49
|
</div>
|
50
50
|
<% if view_type.to_sym == :table %>
|
51
51
|
<% if @resources.present? %>
|
52
|
-
<div class="w-full overflow-auto flex flex-col mt-0">
|
52
|
+
<div class="w-full overflow-auto flex flex-col mt-0 mac-styled-scrollbar">
|
53
53
|
<div class="relative flex-1 flex">
|
54
54
|
<%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource)) %>
|
55
55
|
</div>
|
@@ -63,14 +63,14 @@
|
|
63
63
|
<% if view_type.to_sym == :table %>
|
64
64
|
<% if @models.present? %>
|
65
65
|
<div class="mt-4">
|
66
|
-
<%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_model: @parent_model %>
|
66
|
+
<%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_model: @parent_model, discreet_pagination: field&.discreet_pagination %>
|
67
67
|
</div>
|
68
68
|
<% end %>
|
69
69
|
<% end %>
|
70
70
|
<% if view_type.to_sym == :grid %>
|
71
71
|
<%= render Avo::Index::ResourceGridComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model) %>
|
72
72
|
<div class="mt-6">
|
73
|
-
<%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_model: @parent_model %>
|
73
|
+
<%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_model: @parent_model, discreet_pagination: field&.discreet_pagination %>
|
74
74
|
</div>
|
75
75
|
<% end %>
|
76
76
|
<% end %>
|
@@ -7,59 +7,148 @@
|
|
7
7
|
} do %>
|
8
8
|
<%= render Avo::PanelComponent.new(title: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
|
9
9
|
<% c.tools do %>
|
10
|
-
<% if @
|
11
|
-
<%
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
10
|
+
<% if @resource.has_show_controls? %>
|
11
|
+
<% @resource.render_show_controls.each do |control| %>
|
12
|
+
<% if control.back_button? %>
|
13
|
+
<%= a_link back_path,
|
14
|
+
style: :text,
|
15
|
+
title: control.title,
|
16
|
+
data: {
|
17
|
+
tippy: control.title ? :tooltip : nil,
|
18
|
+
},
|
19
|
+
icon: 'arrow-left' do %>
|
20
|
+
<%= control.label %>
|
21
|
+
<% end %>
|
22
|
+
<% elsif control.delete_button? %>
|
23
|
+
<% if can_see_the_destroy_button? %>
|
24
|
+
<% end %>
|
25
|
+
<%= a_button url: helpers.resource_path(model: @resource.model, resource: @resource),
|
26
|
+
method: :delete,
|
27
|
+
local: true,
|
28
|
+
style: :text,
|
29
|
+
loading: true,
|
30
|
+
confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
|
31
|
+
color: :red,
|
32
|
+
icon: 'trash',
|
33
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
34
|
+
title: control.title,
|
35
|
+
data: {
|
36
|
+
control: :destroy,
|
37
|
+
tippy: control.title ? :tooltip : nil,
|
38
|
+
'resource-id': @resource.model.id,
|
39
|
+
} do %>
|
40
|
+
<% end %>
|
41
|
+
<% elsif control.actions_list? %>
|
42
|
+
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view, exclude: control.exclude, style: control.style, color: control.color %>
|
43
|
+
<% elsif control.edit_button? %>
|
44
|
+
<% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
|
45
|
+
<% end %>
|
46
|
+
<%= a_link edit_path,
|
47
|
+
color: :primary,
|
48
|
+
style: :primary,
|
49
|
+
title: control.title,
|
50
|
+
data: {
|
51
|
+
tippy: control.title ? :tooltip : nil,
|
52
|
+
},
|
53
|
+
icon: 'edit' do %>
|
54
|
+
<%= control.label %>
|
55
|
+
<% end %>
|
56
|
+
<% elsif control.action? %>
|
57
|
+
<%= a_link control.path,
|
58
|
+
color: control.color,
|
59
|
+
style: control.style,
|
60
|
+
icon: control.icon,
|
61
|
+
title: control.title,
|
62
|
+
data: {
|
63
|
+
tippy: control.title ? :tooltip : nil,
|
64
|
+
'turbo-frame': 'actions_show',
|
65
|
+
'action': 'click->actions-picker#visitAction',
|
66
|
+
} do %>
|
67
|
+
<%= control.label %>
|
68
|
+
<% end %>
|
69
|
+
<% elsif control.link_to? %>
|
70
|
+
<%= a_link control.path,
|
71
|
+
color: control.color,
|
72
|
+
style: control.style,
|
73
|
+
icon: control.icon,
|
74
|
+
title: control.title,
|
75
|
+
target: control.target,
|
76
|
+
class: control.class,
|
77
|
+
data: {
|
78
|
+
**control.data,
|
79
|
+
tippy: control.title ? :tooltip : nil,
|
80
|
+
} do %>
|
81
|
+
<%= control.label %>
|
82
|
+
<% end %>
|
83
|
+
<% elsif control.detach_button? %>
|
84
|
+
<% if @reflection.present? && @resource.model.present? && can_detach? %>
|
85
|
+
<%= a_button url: detach_path,
|
86
|
+
icon: 'detach',
|
87
|
+
method: :delete,
|
88
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
89
|
+
style: :text,
|
90
|
+
data: {
|
91
|
+
confirm: "Are you sure you want to detach this #{title}."
|
92
|
+
} do %>
|
93
|
+
<%= t('avo.detach_item', item: title).capitalize %>
|
94
|
+
<% end %>
|
95
|
+
<% end %>
|
30
96
|
<% end %>
|
31
97
|
<% end %>
|
32
98
|
<% else %>
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
99
|
+
<% if @reflection.present? && @resource.model.present? %>
|
100
|
+
<% if can_detach? %>
|
101
|
+
<%= a_button url: detach_path,
|
102
|
+
icon: 'detach',
|
103
|
+
method: :delete,
|
104
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
105
|
+
style: :text,
|
106
|
+
data: {
|
107
|
+
confirm: "Are you sure you want to detach this #{title}."
|
108
|
+
} do %>
|
109
|
+
<%= t('avo.detach_item', item: title).capitalize %>
|
110
|
+
<% end %>
|
111
|
+
<% end %>
|
112
|
+
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
|
113
|
+
<% if can_see_the_edit_button? %>
|
114
|
+
<%= a_link edit_path,
|
115
|
+
color: :primary,
|
116
|
+
style: :primary,
|
117
|
+
icon: 'edit' do %>
|
118
|
+
<%= t('avo.edit').capitalize %>
|
119
|
+
<% end %>
|
120
|
+
<% end %>
|
121
|
+
<% else %>
|
122
|
+
<%= a_link back_path,
|
42
123
|
style: :text,
|
43
|
-
|
44
|
-
|
45
|
-
color: :red,
|
46
|
-
icon: 'trash',
|
47
|
-
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
48
|
-
data: {
|
49
|
-
control: :destroy,
|
50
|
-
'resource-id': @resource.model.id,
|
51
|
-
'tippy': 'tooltip',
|
52
|
-
} do %>
|
53
|
-
<%= t('avo.delete').capitalize %>
|
124
|
+
icon: 'arrow-left' do %>
|
125
|
+
<%= t('avo.go_back') %>
|
54
126
|
<% end %>
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
127
|
+
<% if can_see_the_destroy_button? %>
|
128
|
+
<%= a_button url: helpers.resource_path(model: @resource.model, resource: @resource),
|
129
|
+
method: :delete,
|
130
|
+
local: true,
|
131
|
+
style: :text,
|
132
|
+
loading: true,
|
133
|
+
confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
|
134
|
+
color: :red,
|
135
|
+
icon: 'trash',
|
136
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
137
|
+
data: {
|
138
|
+
control: :destroy,
|
139
|
+
'resource-id': @resource.model.id,
|
140
|
+
} do %>
|
141
|
+
<%= t('avo.delete').capitalize %>
|
142
|
+
<% end %>
|
143
|
+
<% end %>
|
144
|
+
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
|
145
|
+
<% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
|
146
|
+
<%= a_link edit_path,
|
147
|
+
color: :primary,
|
148
|
+
style: :primary,
|
149
|
+
icon: 'edit' do %>
|
150
|
+
<%= t('avo.edit').capitalize %>
|
151
|
+
<% end %>
|
63
152
|
<% end %>
|
64
153
|
<% end %>
|
65
154
|
<% end %>
|
@@ -77,10 +166,12 @@
|
|
77
166
|
<% end %>
|
78
167
|
<% end %>
|
79
168
|
<% end %>
|
80
|
-
|
81
|
-
|
82
|
-
<%
|
83
|
-
|
169
|
+
<% if @reflection.blank? %>
|
170
|
+
<%= content_tag :div, class: 'space-y-12 mt-12' do %>
|
171
|
+
<% @resource.get_items.each_with_index do |item, index| %>
|
172
|
+
<% next if item.nil? %>
|
173
|
+
<%= render Avo::ItemSwitcherComponent.new resource: @resource, reflection: @reflection, item: item, index: index + 1, view: @view %>
|
174
|
+
<% end %>
|
84
175
|
<% end %>
|
85
176
|
<% end %>
|
86
177
|
<% if should_display_invalid_fields_errors? %>
|
@@ -258,18 +258,19 @@ module Avo
|
|
258
258
|
def cast_nullable(params)
|
259
259
|
fields = @resource.get_field_definitions
|
260
260
|
|
261
|
-
nullable_fields = fields
|
262
|
-
field
|
263
|
-
|
261
|
+
nullable_fields = fields
|
262
|
+
.filter do |field|
|
263
|
+
field.nullable
|
264
|
+
end
|
264
265
|
.map do |field|
|
265
|
-
|
266
|
-
|
266
|
+
[field.id, field.null_values]
|
267
|
+
end
|
267
268
|
.to_h
|
268
269
|
|
269
270
|
params.each do |key, value|
|
270
|
-
|
271
|
+
nullable_values = nullable_fields[key.to_sym]
|
271
272
|
|
272
|
-
if
|
273
|
+
if nullable_values.present? && value.in?(nullable_values)
|
273
274
|
params[key] = nil
|
274
275
|
end
|
275
276
|
end
|
data/app/javascript/avo.js
CHANGED
@@ -106,13 +106,10 @@ export default class extends Controller {
|
|
106
106
|
|
107
107
|
// enable timezone display
|
108
108
|
if (this.enableTimeValue) {
|
109
|
-
console.log(1)
|
110
109
|
options.defaultDate = this.parsedValue.setZone(this.displayTimezone).toISO()
|
111
110
|
|
112
111
|
options.dateFormat = 'Y-m-d H:i:S'
|
113
112
|
} else {
|
114
|
-
console.log(2)
|
115
|
-
|
116
113
|
// Because the browser treats the date like a timestamp and updates it at 00:00 hour, when on a western timezone the date will be converted with one day offset.
|
117
114
|
// Ex: 2022-01-30 will render as 2022-01-29 on an American timezone
|
118
115
|
options.defaultDate = universalTimestamp(this.initialValue)
|
@@ -124,6 +121,13 @@ export default class extends Controller {
|
|
124
121
|
}
|
125
122
|
|
126
123
|
onChange(selectedDates) {
|
124
|
+
// No date has been selected
|
125
|
+
if (selectedDates.length === 0) {
|
126
|
+
this.updateRealInput('')
|
127
|
+
|
128
|
+
return
|
129
|
+
}
|
130
|
+
|
127
131
|
let time
|
128
132
|
let args = {}
|
129
133
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<div class="flex flex-col">
|
2
2
|
<%= render Avo::PanelComponent.new(title: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
|
3
3
|
<% c.tools do %>
|
4
|
-
<%= a_link('/admin', icon: 'arrow-left', style: :primary, is_link: true) do %>
|
4
|
+
<%= a_link('/admin', icon: 'arrow-left', color: :green, style: :primary, is_link: true) do %>
|
5
5
|
Primary
|
6
6
|
<% end %>
|
7
7
|
|
data/lib/avo/base_resource.rb
CHANGED
@@ -3,8 +3,8 @@ module Avo
|
|
3
3
|
extend ActiveSupport::DescendantsTracker
|
4
4
|
|
5
5
|
include ActionView::Helpers::UrlHelper
|
6
|
-
include Avo::Concerns::HasModel
|
7
6
|
include Avo::Concerns::HasFields
|
7
|
+
include Avo::Concerns::HasEditableControls
|
8
8
|
include Avo::Concerns::HasStimulusControllers
|
9
9
|
include Avo::Concerns::ModelClassConstantized
|
10
10
|
|
@@ -439,5 +439,9 @@ module Avo
|
|
439
439
|
def ordering_host(**args)
|
440
440
|
Avo::Hosts::Ordering.new resource: self, options: self.class.ordering, **args
|
441
441
|
end
|
442
|
+
|
443
|
+
def has_model_id?
|
444
|
+
model.present? && model.id.present?
|
445
|
+
end
|
442
446
|
end
|
443
447
|
end
|