avo 2.5.2.pre.7 → 2.6.1.pre.2
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 +2 -0
- data/Gemfile.lock +5 -1
- data/app/assets/builds/action_cable.js +2 -0
- data/app/assets/builds/action_cable.js.map +7 -0
- data/app/assets/builds/avo.css +175 -122
- data/app/assets/builds/avo.js +63 -63
- data/app/assets/builds/avo.js.map +3 -3
- data/app/assets/stylesheets/avo.css +33 -1
- 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 +3 -2
- 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 +50 -17
- data/app/components/avo/card_component.rb +12 -0
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +3 -0
- data/app/components/avo/fields/concerns/item_labels.rb +40 -0
- data/app/components/avo/fields/tags_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/tags_field/index_component.html.erb +1 -5
- data/app/components/avo/fields/tags_field/index_component.rb +2 -0
- data/app/components/avo/fields/tags_field/show_component.rb +3 -7
- data/app/components/avo/fields/tags_field/tag_component.html.erb +1 -1
- 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/table_row_component.html.erb +1 -1
- data/app/components/avo/paginator_component.html.erb +2 -2
- 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/group_component.html.erb +4 -2
- data/app/components/avo/sidebar/heading_component.html.erb +1 -1
- data/app/components/avo/sidebar/link_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 +17 -9
- data/app/components/avo/views/resource_new_component.html.erb +8 -2
- data/app/components/avo/views/resource_show_component.html.erb +16 -6
- 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 +3 -3
- data/app/controllers/avo/base_controller.rb +11 -21
- data/app/controllers/avo/private_controller.rb +1 -0
- data/app/controllers/avo/search_controller.rb +33 -13
- data/app/helpers/avo/application_helper.rb +1 -1
- data/app/javascript/js/controllers/fields/key_value_controller.js +1 -1
- data/app/javascript/js/controllers/fields/tags_field_controller.js +3 -3
- data/app/javascript/js/controllers/filter_controller.js +4 -1
- data/app/javascript/js/controllers/search_controller.js +9 -1
- data/app/javascript/js/controllers.js +0 -2
- data/app/views/avo/actions/show.html.erb +5 -2
- data/app/views/avo/dashboards/_chartkick_card.html.erb +1 -1
- data/app/views/avo/dashboards/_metric_card.html.erb +1 -1
- data/app/views/avo/partials/_global_search.html.erb +1 -1
- data/app/views/avo/partials/_logo.html.erb +1 -1
- data/app/views/avo/partials/_navbar.html.erb +9 -6
- data/app/views/avo/partials/_resource_search.html.erb +1 -1
- data/app/views/avo/partials/_table_header.html.erb +3 -2
- data/app/views/avo/private/_links_and_buttons.html.erb +2 -2
- data/app/views/layouts/avo/application.html.erb +50 -53
- data/lib/avo/base_action.rb +24 -6
- data/lib/avo/engine.rb +1 -1
- data/lib/avo/fields/belongs_to_field.rb +4 -4
- data/lib/avo/fields/has_and_belongs_to_many_field.rb +2 -2
- data/lib/avo/fields/has_base_field.rb +2 -0
- data/lib/avo/fields/has_many_field.rb +2 -2
- data/lib/avo/fields/has_one_field.rb +2 -2
- data/lib/avo/fields/tags_field.rb +5 -5
- data/lib/avo/hosts/base_host.rb +2 -0
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
- data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
- data/lib/tasks/avo_tasks.rake +7 -3
- data/public/avo-assets/avo.css +225 -172
- data/public/avo-assets/avo.js +63 -63
- data/public/avo-assets/avo.js.map +3 -3
- metadata +5 -4
- data/app/assets/stylesheets/css/alerts.css +0 -35
- data/app/javascript/js/controllers/alerts_controller.js +0 -26
@@ -12,7 +12,6 @@
|
|
12
12
|
@import './css/buttons.css';
|
13
13
|
@import './css/typography.css';
|
14
14
|
@import './css/tooltips.css';
|
15
|
-
@import './css/alerts.css';
|
16
15
|
@import './css/loader.css';
|
17
16
|
@import './css/pagination.css';
|
18
17
|
@import './css/breadcrumbs.css';
|
@@ -91,3 +90,36 @@ trix-editor {
|
|
91
90
|
max-height: 320px !important;
|
92
91
|
overflow-y: auto;
|
93
92
|
}
|
93
|
+
|
94
|
+
.scroll-shadows {
|
95
|
+
background:
|
96
|
+
/* Shadow Cover TOP */
|
97
|
+
linear-gradient(
|
98
|
+
#F6F6F7 30%,
|
99
|
+
#F6F6F7
|
100
|
+
) center top,
|
101
|
+
|
102
|
+
/* Shadow Cover BOTTOM */
|
103
|
+
linear-gradient(
|
104
|
+
#F6F6F7,
|
105
|
+
#F6F6F7 70%
|
106
|
+
) center bottom,
|
107
|
+
|
108
|
+
/* Shadow TOP */
|
109
|
+
radial-gradient(
|
110
|
+
farthest-side at 50% 0,
|
111
|
+
rgba(0, 0, 0, 0.2),
|
112
|
+
rgba(0, 0, 0, 0)
|
113
|
+
) center top,
|
114
|
+
|
115
|
+
/* Shadow BOTTOM */
|
116
|
+
radial-gradient(
|
117
|
+
farthest-side at 50% 100%,
|
118
|
+
rgba(0, 0, 0, 0.2),
|
119
|
+
rgba(0, 0, 0, 0)
|
120
|
+
) center bottom;
|
121
|
+
|
122
|
+
background-repeat: no-repeat;
|
123
|
+
background-size: 100% 34px, 100% 34px, 100% 14px, 100% 14px;
|
124
|
+
background-attachment: local, local, scroll, scroll;
|
125
|
+
}
|
@@ -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',
|
@@ -34,7 +35,7 @@
|
|
34
35
|
'actions-picker-target': action.standalone ? 'standaloneAction' : 'resourceAction',
|
35
36
|
'disabled': disabled,
|
36
37
|
},
|
37
|
-
class: "flex items-center px-4 py-
|
38
|
+
class: "flex items-center px-4 py-3 w-full font-semibold text-sm #{disabled ? 'text-gray-500' : 'text-black hover:bg-blue-500 hover:text-white'}" do %>
|
38
39
|
<%= svg 'play', class: 'h-5 mr-1 inline' %> <%= action.action_name %>
|
39
40
|
<% end %>
|
40
41
|
<% end %>
|
@@ -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
|
@@ -38,14 +38,15 @@ class Avo::ButtonComponent < ViewComponent::Base
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def button_classes
|
41
|
-
classes = "button-component inline-flex flex-grow-0 items-center
|
41
|
+
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}"
|
42
42
|
|
43
43
|
classes += " rounded" if @rounded.present?
|
44
44
|
|
45
45
|
classes += style_classes
|
46
46
|
|
47
|
-
classes +=
|
48
|
-
classes +=
|
47
|
+
classes += horizontal_padding_classes
|
48
|
+
classes += vertical_padding_classes
|
49
|
+
classes += text_size_classes
|
49
50
|
|
50
51
|
classes
|
51
52
|
end
|
@@ -57,10 +58,14 @@ class Avo::ButtonComponent < ViewComponent::Base
|
|
57
58
|
def full_content
|
58
59
|
result = ""
|
59
60
|
icon_classes = @icon_class
|
60
|
-
|
61
|
+
# space out the icon from the text if text is present
|
62
|
+
icon_classes += " mr-1" if content.present?
|
63
|
+
# add the icon height
|
64
|
+
icon_classes += icon_size_classes
|
61
65
|
|
66
|
+
# Add the icon
|
62
67
|
result += helpers.svg(@icon, class: icon_classes) if @icon.present?
|
63
|
-
|
68
|
+
|
64
69
|
if content.present?
|
65
70
|
result += "<span>#{content}</span>"
|
66
71
|
end
|
@@ -96,49 +101,77 @@ class Avo::ButtonComponent < ViewComponent::Base
|
|
96
101
|
|
97
102
|
private
|
98
103
|
|
99
|
-
def
|
104
|
+
def vertical_padding_classes
|
100
105
|
case @size.to_sym
|
101
106
|
when :xs
|
102
107
|
" py-0"
|
103
108
|
when :sm
|
104
109
|
" py-1"
|
105
110
|
when :md
|
106
|
-
" py-
|
111
|
+
" py-1.5"
|
107
112
|
when :lg
|
113
|
+
" py-2"
|
114
|
+
when :xl
|
108
115
|
" py-3"
|
109
116
|
else
|
110
117
|
""
|
111
118
|
end
|
112
119
|
end
|
113
120
|
|
121
|
+
def horizontal_padding_classes
|
122
|
+
return " px-1" if @compact
|
123
|
+
|
124
|
+
case @size.to_sym
|
125
|
+
when :xs
|
126
|
+
" px-2"
|
127
|
+
when :sm
|
128
|
+
" px-3"
|
129
|
+
when :md
|
130
|
+
" px-3"
|
131
|
+
when :lg
|
132
|
+
" px-5"
|
133
|
+
when :xl
|
134
|
+
" px-6"
|
135
|
+
else
|
136
|
+
"px-4"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def text_size_classes
|
141
|
+
case @size.to_sym
|
142
|
+
when :xs
|
143
|
+
" text-xs"
|
144
|
+
else
|
145
|
+
" text-sm"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
114
149
|
def style_classes
|
115
150
|
case @style
|
116
151
|
when :primary
|
117
152
|
" 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
153
|
when :outline
|
119
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"
|
155
|
+
when :text
|
156
|
+
" text-#{@color}-500 active:outline-#{@color}-500 hover:bg-gray-100 border-transparent"
|
120
157
|
else
|
121
158
|
""
|
122
159
|
end
|
123
160
|
end
|
124
161
|
|
125
|
-
def
|
162
|
+
def icon_size_classes
|
126
163
|
icon_classes = ""
|
127
164
|
|
128
165
|
case @size
|
129
166
|
when :xs
|
130
|
-
icon_classes += " h-4"
|
131
|
-
# When icon is solo we need to add an offset
|
132
|
-
icon_classes += " my-1" if content.blank?
|
167
|
+
icon_classes += " h-4 my-1"
|
133
168
|
when :sm
|
134
|
-
icon_classes += " h-4"
|
135
|
-
# When icon is solo we need to add an offset
|
136
|
-
icon_classes += " my-1" if content.blank?
|
169
|
+
icon_classes += " h-4 my-1"
|
137
170
|
when :md
|
138
|
-
icon_classes += " h-
|
139
|
-
# When icon is solo we need to add an offset
|
140
|
-
icon_classes += " my-0.5" if content.blank?
|
171
|
+
icon_classes += " h-4 my-1"
|
141
172
|
when :lg
|
173
|
+
icon_classes += " h-5 my-0.5"
|
174
|
+
when :xl
|
142
175
|
icon_classes += " h-6"
|
143
176
|
end
|
144
177
|
|
@@ -3,9 +3,21 @@
|
|
3
3
|
class Avo::CardComponent < ViewComponent::Base
|
4
4
|
def initialize(card: nil)
|
5
5
|
@card = card
|
6
|
+
|
7
|
+
init_card
|
6
8
|
end
|
7
9
|
|
8
10
|
def render?
|
9
11
|
!@card.nil?
|
10
12
|
end
|
13
|
+
|
14
|
+
# Initializing the card byt running the query method.
|
15
|
+
# We'll still keep the query block around for compatibility reasons.
|
16
|
+
def init_card
|
17
|
+
if @card.respond_to? :query
|
18
|
+
@card.query
|
19
|
+
elsif @card.query_block.present?
|
20
|
+
@card.compute_result
|
21
|
+
end
|
22
|
+
end
|
11
23
|
end
|
@@ -7,6 +7,9 @@
|
|
7
7
|
data-via-association-id="<%= @field.id %>"
|
8
8
|
data-via-reflection-id="<%= @field.model.id %>"
|
9
9
|
data-via-reflection-class="<%= @field.model.class.to_s %>"
|
10
|
+
data-via-parent-resource-id="<%= params[:via_resource_id] %>"
|
11
|
+
data-via-parent-resource-class="<%= params[:via_relation_class] %>"
|
12
|
+
data-via-relation="<%= params[:via_relation] %>"
|
10
13
|
></div>
|
11
14
|
<div class="relative w-full" autocomplete="off">
|
12
15
|
<%= @form.text_field @foreign_key,
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Avo
|
2
|
+
module Fields
|
3
|
+
module Concerns
|
4
|
+
module ItemLabels
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def value_for_item(item)
|
8
|
+
if @field.acts_as_taggable_on.present?
|
9
|
+
item["value"]
|
10
|
+
else
|
11
|
+
item
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def label_from_item(item)
|
16
|
+
value = value_for_item item
|
17
|
+
|
18
|
+
if suggestions_are_a_hash?
|
19
|
+
return suggestions_by_id[value.to_s][:label] if suggestions_by_id[value.to_s].present?
|
20
|
+
end
|
21
|
+
value
|
22
|
+
end
|
23
|
+
|
24
|
+
def suggestions_by_id
|
25
|
+
return {} unless suggestions_are_a_hash?
|
26
|
+
|
27
|
+
@field.suggestions.map do |suggestion|
|
28
|
+
[suggestion[:value].to_s, suggestion]
|
29
|
+
end.to_h
|
30
|
+
end
|
31
|
+
|
32
|
+
def suggestions_are_a_hash?
|
33
|
+
return false if @field.suggestions.blank?
|
34
|
+
|
35
|
+
@field.suggestions.first.is_a? Hash
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -18,7 +18,7 @@
|
|
18
18
|
data: {
|
19
19
|
'tags-field-target': 'input',
|
20
20
|
'whitelist-items': @field.suggestions.to_json,
|
21
|
-
'
|
21
|
+
'disallowed-items': @field.disallowed.to_json,
|
22
22
|
'enforce-suggestions': @field.enforce_suggestions ? 1 : 0,
|
23
23
|
'delimiters': @field.delimiters,
|
24
24
|
'close-on-select': @field.close_on_select ? 1 : 0,
|
@@ -1,11 +1,7 @@
|
|
1
1
|
<%= index_field_wrapper field: @field do %>
|
2
2
|
<div class="flex gap-1 items-center flex-nowrap">
|
3
3
|
<% value.take(3).each do |item| %>
|
4
|
-
|
5
|
-
<%= render Avo::Fields::TagsField::TagComponent.new(label: item['value']) %>
|
6
|
-
<% else %>
|
7
|
-
<%= render Avo::Fields::TagsField::TagComponent.new(label: item) %>
|
8
|
-
<% end %>
|
4
|
+
<%= render Avo::Fields::TagsField::TagComponent.new(label: label_from_item(item)) %>
|
9
5
|
<% end %>
|
10
6
|
<% if value.count > 3 %>
|
11
7
|
<%= render Avo::Fields::TagsField::TagComponent.new(label: '...', title: I18n.t('avo.x_items_more', count: value.count - 3)) %>
|
@@ -1,11 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# require_relative 'item_labels'
|
4
|
+
|
3
5
|
class Avo::Fields::TagsField::ShowComponent < Avo::Fields::ShowComponent
|
4
|
-
|
5
|
-
if @field.acts_as_taggable_on.present?
|
6
|
-
item['value']
|
7
|
-
else
|
8
|
-
item
|
9
|
-
end
|
10
|
-
end
|
6
|
+
include Avo::Fields::Concerns::ItemLabels
|
11
7
|
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-base <%= 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 %>
|
@@ -25,9 +25,9 @@
|
|
25
25
|
</div>
|
26
26
|
<% per_page_options.each do |option| %>
|
27
27
|
<% if parent_model.present? %>
|
28
|
-
<%= link_to "Change to #{option} items per page", helpers.related_resources_path(parent_model, parent_model, per_page: option, keep_query_params: true), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
|
28
|
+
<%= 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 %>
|
29
29
|
<% else %>
|
30
|
-
<%= link_to "Change to #{option} items per page", helpers.resources_path(resource: resource, per_page: option, keep_query_params: true), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
|
30
|
+
<%= 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 %>
|
31
31
|
<% end %>
|
32
32
|
<% end %>
|
33
33
|
</div>
|
@@ -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
|
@@ -7,7 +7,9 @@
|
|
7
7
|
<% end %>
|
8
8
|
>
|
9
9
|
<% if item.name.present? %>
|
10
|
-
<div
|
10
|
+
<div
|
11
|
+
class="flex justify-between px-10 pr-2 pt-2 pb-0 text-gray-400"
|
12
|
+
>
|
11
13
|
<div class="flex items-center text-xs uppercase font-semibold leading-none">
|
12
14
|
<%= item.name %>
|
13
15
|
</div>
|
@@ -17,7 +19,7 @@
|
|
17
19
|
data-menu-target="svg"
|
18
20
|
data-menu-key-param="<%= key %>"
|
19
21
|
>
|
20
|
-
<%= helpers.svg 'heroicons/outline/chevron-down', class: "h-4"%>
|
22
|
+
<%= helpers.svg 'heroicons/outline/chevron-down', class: "h-4 mr-0.5"%>
|
21
23
|
</div>
|
22
24
|
<% end %>
|
23
25
|
</div>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="flex justify-between
|
1
|
+
<div class="flex justify-between px-4 pr-2 py-1 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>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<%= send link_method, path, class: classes, active: active, target: target do %>
|
3
3
|
<%= label %>
|
4
4
|
<% if target == :_blank %>
|
5
|
-
<%= helpers.svg('heroicons/outline/external-link', class: 'self-center ml-auto h-3') %>
|
5
|
+
<%= helpers.svg('heroicons/outline/external-link', class: 'self-center ml-auto h-3 mr-2') %>
|
6
6
|
<% end %>
|
7
7
|
<% end %>
|
8
8
|
<% else %>
|
@@ -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 pr-0 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 w-64 hidden lg:flex flex-1 border-r lg:border-none bg-none h-[calc(100vh-4rem)] bg-gray-25 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? %>
|