avo 2.2.2 → 2.3.0
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/components/avo/sidebar/group_component.html.erb +4 -4
- data/app/components/avo/sidebar/heading_component.html.erb +1 -1
- data/app/components/avo/sidebar/heading_component.rb +3 -1
- data/app/components/avo/sidebar/section_component.html.erb +3 -3
- data/app/controllers/avo/base_controller.rb +9 -1
- data/app/javascript/avo.js +13 -0
- data/app/javascript/js/controllers/menu_controller.js +23 -18
- data/lib/avo/services/authorization_service.rb +8 -2
- data/lib/avo/version.rb +1 -1
- data/public/avo-assets/avo.js +54 -54
- data/public/avo-assets/avo.js.map +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7aa88764021f40e6a32625569658172b802aa0c2ca31e0fb282cafa5ccc8ba33
|
4
|
+
data.tar.gz: 6e256e598fa099862691a623edfee9d53d0723d0101e681090686e4edd2ae460
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab132521622ae3dd8dfa75cbf513383b42e6361d64188ced7751560d9808c7b3bb591588ebe831460c992c1d0ee3a6aebed2abfce923d06ccb21da0502373c64
|
7
|
+
data.tar.gz: 3e60dfffdae92341ece77e3bf62236d6104db247399afea1fd6d7a684ad9d1323eff9be12f180ab9ee76f2097036f7cbb48a45720873b66e9dc958b4a0d8fbbf
|
data/Gemfile.lock
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
data-controller="menu"
|
4
4
|
data-menu-target="self"
|
5
5
|
data-menu-key-param="<%= key %>"
|
6
|
-
data-menu-collapsed-
|
6
|
+
data-menu-default-collapsed-state="<%= collapsed ? 'collapsed' : 'expanded' %>"
|
7
7
|
<% end %>
|
8
8
|
>
|
9
9
|
<div class="flex justify-between px-10 pt-2 pb-0 text-gray-600 ">
|
@@ -11,16 +11,16 @@
|
|
11
11
|
<%= item.name %>
|
12
12
|
</div>
|
13
13
|
<% if collapsable %>
|
14
|
-
<div class="cursor-pointer"
|
14
|
+
<div class="cursor-pointer <%= 'rotate-90' if collapsed %>"
|
15
15
|
data-action="click->menu#triggerCollapse"
|
16
16
|
data-menu-target="svg"
|
17
17
|
data-menu-key-param="<%= key %>"
|
18
18
|
>
|
19
|
-
<%= helpers.svg 'heroicons/outline/chevron-down', class:
|
19
|
+
<%= helpers.svg 'heroicons/outline/chevron-down', class: "h-4"%>
|
20
20
|
</div>
|
21
21
|
<% end %>
|
22
22
|
</div>
|
23
|
-
<div class="w-full space-y-1" data-menu-target="items">
|
23
|
+
<div class="w-full space-y-1 <%= 'hidden' if collapsed %>" data-menu-target="items">
|
24
24
|
<% items.each do |item| %>
|
25
25
|
<%= render Avo::Sidebar::ItemSwitcherComponent.new item: item %>
|
26
26
|
<% end %>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<span class="min-w-[20px]"><%= icon %></span> <span><%= label %></span>
|
4
4
|
</div>
|
5
5
|
<% if collapsable %>
|
6
|
-
<div class="cursor-pointer"
|
6
|
+
<div class="cursor-pointer <%= 'rotate-90' if collapsed %>"
|
7
7
|
data-action="click->menu#triggerCollapse"
|
8
8
|
data-menu-key-param="<%= key %>"
|
9
9
|
data-menu-target="svg"
|
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
class Avo::Sidebar::HeadingComponent < ViewComponent::Base
|
4
4
|
attr_reader :collapsable
|
5
|
+
attr_reader :collapsed
|
5
6
|
attr_reader :icon
|
6
7
|
attr_reader :key
|
7
8
|
attr_reader :label
|
8
9
|
|
9
|
-
def initialize(label: nil, icon: nil, collapsable: false, key: nil)
|
10
|
+
def initialize(label: nil, icon: nil, collapsable: false, collapsed: false, key: nil)
|
10
11
|
@collapsable = collapsable
|
12
|
+
@collapsed = collapsed
|
11
13
|
@icon = icon
|
12
14
|
@key = key
|
13
15
|
@label = label
|
@@ -3,11 +3,11 @@
|
|
3
3
|
data-controller="menu"
|
4
4
|
data-menu-target="self"
|
5
5
|
data-menu-key-param="<%= key %>"
|
6
|
-
data-menu-collapsed-
|
6
|
+
data-menu-default-collapsed-state="<%= collapsed ? 'collapsed' : 'expanded' %>"
|
7
7
|
<% end %>
|
8
8
|
>
|
9
|
-
<%= render Avo::Sidebar::HeadingComponent.new label: item.name, icon: helpers.svg(icon, class:
|
10
|
-
<div class="w-full space-y-1" data-menu-target="items">
|
9
|
+
<%= render Avo::Sidebar::HeadingComponent.new label: item.name, icon: helpers.svg(icon, class: "h-5"), collapsable: item.collapsable, collapsed: collapsed, key: key %>
|
10
|
+
<div class="w-full space-y-1 <%= 'hidden' if collapsed %>" data-menu-target="items">
|
11
11
|
<% items.each do |item| %>
|
12
12
|
<%= render Avo::Sidebar::ItemSwitcherComponent.new item: item %>
|
13
13
|
<% end %>
|
@@ -44,7 +44,15 @@ module Avo
|
|
44
44
|
unless @index_params[:sort_by].eql? :created_at
|
45
45
|
@query = @query.unscope(:order)
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
|
+
# Check if the sortable field option is actually a proc and we need to do a custom sort
|
49
|
+
field_id = @index_params[:sort_by].to_sym
|
50
|
+
field = @resource.get_field_definitions.find { |field| field.id == field_id }
|
51
|
+
if field&.sortable.is_a?(Proc)
|
52
|
+
@query = field.sortable.call(@query, @index_params[:sort_direction])
|
53
|
+
else
|
54
|
+
@query = @query.order("#{@resource.model_class.table_name}.#{@index_params[:sort_by]} #{@index_params[:sort_direction]}")
|
55
|
+
end
|
48
56
|
end
|
49
57
|
|
50
58
|
# Apply filters
|
data/app/javascript/avo.js
CHANGED
@@ -84,3 +84,16 @@ document.addEventListener('turbo:submit-end', () => document.body.classList.remo
|
|
84
84
|
document.addEventListener('turbo:before-cache', () => {
|
85
85
|
document.querySelectorAll('[data-turbo-remove-before-cache]').forEach((element) => element.remove())
|
86
86
|
})
|
87
|
+
|
88
|
+
window.Avo = window.Avo || { configuration: {} }
|
89
|
+
|
90
|
+
window.Avo.menus = {
|
91
|
+
resetCollapsedState() {
|
92
|
+
Array.from(document.querySelectorAll('[data-menu-key-param]'))
|
93
|
+
.map((i) => i.getAttribute('data-menu-key-param'))
|
94
|
+
.filter(Boolean)
|
95
|
+
.forEach((key) => {
|
96
|
+
window.localStorage.removeItem(key)
|
97
|
+
})
|
98
|
+
},
|
99
|
+
}
|
@@ -1,31 +1,46 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
2
|
-
import isNull from 'lodash/isNull'
|
3
2
|
|
4
3
|
export default class extends Controller {
|
5
4
|
static targets = ['svg', 'items', 'self'];
|
6
5
|
|
7
|
-
collapsed =
|
6
|
+
collapsed = true;
|
8
7
|
|
9
8
|
get key() {
|
10
9
|
return this.selfTarget.getAttribute('data-menu-key-param')
|
11
10
|
}
|
12
11
|
|
13
|
-
defaultState() {
|
14
|
-
return this.selfTarget.getAttribute('data-menu-collapsed-
|
12
|
+
get defaultState() {
|
13
|
+
return this.selfTarget.getAttribute('data-menu-default-collapsed-state')
|
14
|
+
}
|
15
|
+
|
16
|
+
get userState() {
|
17
|
+
return window.localStorage.getItem(this.key)
|
18
|
+
}
|
19
|
+
|
20
|
+
set userState(payload) {
|
21
|
+
window.localStorage.setItem(this.key, payload)
|
22
|
+
}
|
23
|
+
|
24
|
+
get initiallyCollapsed() {
|
25
|
+
if (this.userState === 'collapsed' || this.defaultState === 'collapsed') return true
|
26
|
+
if (this.userState === 'expanded' || this.defaultState === 'expanded') return false
|
27
|
+
|
28
|
+
return false
|
15
29
|
}
|
16
30
|
|
17
31
|
connect() {
|
18
|
-
if (this.
|
19
|
-
this.collapsed = true
|
20
|
-
this.markCollapsed()
|
21
|
-
} else if (isNull(this.getState()) && this.defaultState()) {
|
32
|
+
if (this.initiallyCollapsed) {
|
22
33
|
this.collapsed = true
|
23
34
|
this.markCollapsed()
|
35
|
+
} else {
|
36
|
+
this.collapsed = false
|
37
|
+
this.markExpanded()
|
24
38
|
}
|
25
39
|
}
|
26
40
|
|
27
41
|
triggerCollapse() {
|
28
42
|
this.collapsed = !this.collapsed
|
43
|
+
this.userState = this.collapsed ? 'collapsed' : 'expanded'
|
29
44
|
|
30
45
|
this.updateDom()
|
31
46
|
}
|
@@ -41,20 +56,10 @@ export default class extends Controller {
|
|
41
56
|
markCollapsed() {
|
42
57
|
this.svgTarget.classList.add('rotate-90')
|
43
58
|
this.itemsTarget.classList.add('hidden')
|
44
|
-
this.storeState('collapsed')
|
45
59
|
}
|
46
60
|
|
47
61
|
markExpanded() {
|
48
62
|
this.svgTarget.classList.remove('rotate-90')
|
49
63
|
this.itemsTarget.classList.remove('hidden')
|
50
|
-
this.storeState('expanded')
|
51
|
-
}
|
52
|
-
|
53
|
-
getState() {
|
54
|
-
return window.localStorage.getItem(this.key)
|
55
|
-
}
|
56
|
-
|
57
|
-
storeState(payload) {
|
58
|
-
window.localStorage.setItem(this.key, payload)
|
59
64
|
}
|
60
65
|
}
|
@@ -68,11 +68,17 @@ module Avo
|
|
68
68
|
def authorize_action(user, record, action, **args)
|
69
69
|
action = Avo.configuration.authorization_methods.stringify_keys[action.to_s] || action
|
70
70
|
|
71
|
+
# If no action passed we should raise error if the user wants that.
|
72
|
+
# If not, just allow it.
|
73
|
+
if action.nil?
|
74
|
+
raise Pundit::NotDefinedError.new 'Policy method is missing' if Avo.configuration.raise_error_on_missing_policy
|
75
|
+
|
76
|
+
return true
|
77
|
+
end
|
78
|
+
|
71
79
|
# Add the question mark if it's missing
|
72
80
|
action = "#{action}?" unless action.end_with? '?'
|
73
81
|
|
74
|
-
return true if action.nil?
|
75
|
-
|
76
82
|
authorize user, record, action, **args
|
77
83
|
end
|
78
84
|
|
data/lib/avo/version.rb
CHANGED