avo 2.2.2 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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