avo 1.23.0 → 1.24.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 +2 -0
- data/Gemfile.lock +4 -1
- data/app/assets/svgs/arrow-down.svg +3 -0
- data/app/assets/svgs/arrow-up.svg +3 -0
- data/app/assets/svgs/download-solid-reversed.svg +3 -0
- data/app/assets/svgs/download-solid.svg +3 -0
- data/app/assets/svgs/switch-vertical.svg +3 -0
- data/app/components/avo/base_component.rb +7 -0
- data/app/components/avo/index/grid_item_component.html.erb +1 -1
- data/app/components/avo/index/ordering/base_component.rb +9 -0
- data/app/components/avo/index/ordering/button_component.html.erb +10 -0
- data/app/components/avo/index/ordering/button_component.rb +31 -0
- data/app/components/avo/index/ordering/buttons_component.html.erb +30 -0
- data/app/components/avo/index/ordering/buttons_component.rb +19 -0
- data/app/components/avo/index/resource_controls_component.html.erb +11 -4
- data/app/components/avo/index/resource_controls_component.rb +6 -1
- data/app/components/avo/index/table_row_component.html.erb +1 -1
- data/app/components/avo/resource_component.rb +1 -1
- data/app/components/avo/turbo_frame_wrapper_component.html.erb +3 -1
- data/app/controllers/avo/application_controller.rb +7 -1
- data/app/controllers/avo/base_controller.rb +14 -1
- data/app/helpers/avo/url_helpers.rb +4 -0
- data/app/javascript/js/application.js +4 -0
- data/config/routes.rb +3 -0
- data/lib/avo/base_resource.rb +8 -0
- data/lib/avo/licensing/pro_license.rb +1 -0
- data/lib/avo/version.rb +1 -1
- data/public/avo-assets/avo.css +4 -0
- data/public/avo-assets/avo.js +7633 -7374
- data/public/avo-assets/avo.js.map +3 -3
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3bd7ab9c0d5e4743874638117c67d87e723a4300ef8342be0c3ef868ce0a07e2
|
4
|
+
data.tar.gz: 8229f364c7341342e7ac25a8da2be3fc15d10a1feeeb7c5f8c2a6fc270c4cde6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd6e21cbe3c211a4fa669970b9de4ead47566712fc6dadbcbce0c08e2d1cbf21cdd73e63e05677cc53cff591fb7420651aa8f8048f2329a760de8458addf2ed0
|
7
|
+
data.tar.gz: 98c83f4ea0c66bdb5016c650c1f29fd14f0a98f45a4bd024f5d0285d34bbb8a296d3cce94457443e95f6cff4293cac11155ce13339c6c9d5c630af9119669aaa
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (1.
|
4
|
+
avo (1.24.0)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
@@ -81,6 +81,8 @@ GEM
|
|
81
81
|
minitest (>= 5.1)
|
82
82
|
tzinfo (~> 2.0)
|
83
83
|
zeitwerk (~> 2.3)
|
84
|
+
acts_as_list (1.0.4)
|
85
|
+
activerecord (>= 4.2)
|
84
86
|
addressable (2.8.0)
|
85
87
|
public_suffix (>= 2.0.2, < 5.0)
|
86
88
|
ap (0.1.1)
|
@@ -397,6 +399,7 @@ PLATFORMS
|
|
397
399
|
|
398
400
|
DEPENDENCIES
|
399
401
|
active_link_to
|
402
|
+
acts_as_list
|
400
403
|
addressable
|
401
404
|
ap
|
402
405
|
appraisal
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" transform="rotate(-180)">
|
2
|
+
<path fill-rule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" />
|
3
|
+
</svg>
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
2
|
+
<path fill-rule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" />
|
3
|
+
</svg>
|
@@ -32,7 +32,7 @@
|
|
32
32
|
</div>
|
33
33
|
</div>
|
34
34
|
<div class="w-full place-self-end">
|
35
|
-
<%= render(Avo::Index::ResourceControlsComponent.new(resource: @resource, reflection: @reflection, parent_model: @parent_model)) %>
|
35
|
+
<%= render(Avo::Index::ResourceControlsComponent.new(resource: @resource, reflection: @reflection, parent_model: @parent_model, view_type: :grid)) %>
|
36
36
|
</div>
|
37
37
|
</div>
|
38
38
|
</div>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<%= button_to order_path(direction: direction, referrer: request.fullpath),
|
2
|
+
title: t("avo.order.#{direction}").capitalize,
|
3
|
+
method: :patch,
|
4
|
+
class: 'flex items-center',
|
5
|
+
data: {
|
6
|
+
target: "order:#{direction}",
|
7
|
+
'tippy': 'tooltip',
|
8
|
+
} do %>
|
9
|
+
<%= helpers.svg(svg, class: 'text-gray-400 h-6 hover:text-gray-600') %>
|
10
|
+
<% end %>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Avo::Index::Ordering::ButtonComponent < Avo::Index::Ordering::BaseComponent
|
4
|
+
attr_reader :resource
|
5
|
+
attr_reader :direction
|
6
|
+
attr_reader :svg
|
7
|
+
|
8
|
+
def initialize(resource: nil, direction: nil, svg: nil)
|
9
|
+
@resource = resource
|
10
|
+
@direction = direction
|
11
|
+
@svg = svg
|
12
|
+
end
|
13
|
+
|
14
|
+
def render?
|
15
|
+
order_actions[direction].present?
|
16
|
+
end
|
17
|
+
|
18
|
+
def order_path(args)
|
19
|
+
path = "#{::Avo::App.root_path}/resources/#{resource.route_key}/#{resource.model.id}/order"
|
20
|
+
|
21
|
+
if args.present?
|
22
|
+
string_args = args.map do |key, value|
|
23
|
+
"#{key}=#{value}"
|
24
|
+
end.join('&')
|
25
|
+
|
26
|
+
path = "#{path}?#{string_args}"
|
27
|
+
end
|
28
|
+
|
29
|
+
path
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<div class="flex items-center justify-center">
|
2
|
+
<% unless always_visible? %>
|
3
|
+
<div class="popover inline-block"
|
4
|
+
data-controller="popover"
|
5
|
+
data-popover-translate-x="-100%"
|
6
|
+
data-popover-translate-y="-32px"
|
7
|
+
data-action="mouseover->popover#mouseOver mouseout->popover#mouseOut"
|
8
|
+
>
|
9
|
+
<%= button_tag nil,
|
10
|
+
title: t('avo.order.reorder_record').capitalize,
|
11
|
+
class: 'flex items-center',
|
12
|
+
data: {
|
13
|
+
'tippy': 'tooltip',
|
14
|
+
} do
|
15
|
+
%>
|
16
|
+
<%= helpers.svg('switch-vertical', class: 'text-gray-400 h-6 hover:text-gray-600') %>
|
17
|
+
<% end %>
|
18
|
+
<% end %>
|
19
|
+
<% if always_visible? %>
|
20
|
+
<div class="flex max-w-xs rounded">
|
21
|
+
<% else %>
|
22
|
+
<div class="flex hidden absolute max-w-xs bg-white rounded p-2 z-40" data-popover-target="content">
|
23
|
+
<% end %>
|
24
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, direction: :higher, svg: 'arrow-up' %>
|
25
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, direction: :lower, svg: 'arrow-down' %>
|
26
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, direction: :to_top, svg: 'download-solid-reversed' %>
|
27
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, direction: :to_bottom, svg: 'download-solid' %>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
</div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Avo::Index::Ordering::ButtonsComponent < Avo::Index::Ordering::BaseComponent
|
4
|
+
def initialize(resource: nil)
|
5
|
+
@resource = resource
|
6
|
+
end
|
7
|
+
|
8
|
+
def render?
|
9
|
+
can_order_any?
|
10
|
+
end
|
11
|
+
|
12
|
+
def can_order_any?
|
13
|
+
order_actions.present?
|
14
|
+
end
|
15
|
+
|
16
|
+
def always_visible?
|
17
|
+
@resource.class.ordering[:always_visible]
|
18
|
+
end
|
19
|
+
end
|
@@ -1,14 +1,18 @@
|
|
1
|
-
<div class="space-x-2 flex flex-row justify-around w-full">
|
1
|
+
<div class="space-x-2 flex flex-row justify-around items-center w-full">
|
2
|
+
<% if view_is_table? && has_with_trial(:resource_ordering) %>
|
3
|
+
<%= render Avo::Index::Ordering::ButtonsComponent.new resource: @resource %>
|
4
|
+
<% end %>
|
5
|
+
|
2
6
|
<% if can_view? %>
|
3
7
|
<%= link_to helpers.svg('eye', class: 'text-gray-400 h-6 hover:text-gray-600'),
|
4
8
|
show_path,
|
5
|
-
title: t('avo.view_item',
|
9
|
+
title: t('avo.view_item', item: singular_resource_name).capitalize,
|
6
10
|
data: {
|
7
11
|
target: 'control:view',
|
8
12
|
control: :show,
|
9
13
|
'tippy': 'tooltip',
|
10
14
|
}
|
11
|
-
|
15
|
+
%>
|
12
16
|
<% end %>
|
13
17
|
|
14
18
|
<% if can_edit? %>
|
@@ -45,7 +49,10 @@
|
|
45
49
|
<% end %>
|
46
50
|
|
47
51
|
<% if can_delete? %>
|
48
|
-
<%= form_with url: helpers.resource_path(model: @resource.model, resource: @resource),
|
52
|
+
<%= form_with url: helpers.resource_path(model: @resource.model, resource: @resource),
|
53
|
+
method: :delete,
|
54
|
+
class: 'flex items-center',
|
55
|
+
html: {
|
49
56
|
'data-turbo-frame': params[:turbo_frame]
|
50
57
|
} do |form| %>
|
51
58
|
<%= form.button helpers.svg('trash', class: 'text-gray-400 h-6 hover:text-gray-600'),
|
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
|
4
|
-
def initialize(resource: nil, reflection: nil, parent_model: nil)
|
4
|
+
def initialize(resource: nil, reflection: nil, parent_model: nil, view_type: :table)
|
5
5
|
@resource = resource
|
6
6
|
@reflection = reflection
|
7
7
|
@parent_model = parent_model
|
8
|
+
@view_type = view_type
|
8
9
|
end
|
9
10
|
|
10
11
|
def can_detach?
|
@@ -69,4 +70,8 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
|
|
69
70
|
def is_has_many_association
|
70
71
|
@reflection.is_a?(::ActiveRecord::Reflection::HasManyReflection) || @reflection.is_a?(::ActiveRecord::Reflection::ThroughReflection)
|
71
72
|
end
|
73
|
+
|
74
|
+
def view_is_table?
|
75
|
+
@view_type == :table
|
76
|
+
end
|
72
77
|
end
|
@@ -12,7 +12,7 @@
|
|
12
12
|
<% end %>
|
13
13
|
<td class="text-right whitespace-nowrap px-2">
|
14
14
|
<div class="flex items-center justify-end flex-grow-0 h-full w-full">
|
15
|
-
<%= render(Avo::Index::ResourceControlsComponent.new(resource: @resource, reflection: @reflection, parent_model: @parent_model)) %>
|
15
|
+
<%= render(Avo::Index::ResourceControlsComponent.new(resource: @resource, reflection: @reflection, parent_model: @parent_model, view_type: :table)) %>
|
16
16
|
</div>
|
17
17
|
</td>
|
18
18
|
</tr>
|
@@ -3,7 +3,9 @@
|
|
3
3
|
# When rendering the frames the flashed content gets lost.
|
4
4
|
# By including the alerts partial, the stimulus will pick them up and display them to the user.
|
5
5
|
%>
|
6
|
-
|
6
|
+
<% if helpers.turbo_frame_request? %>
|
7
|
+
<%= render Avo::AlertsComponent.new if helpers.flash.present? && name.present? %>
|
8
|
+
<% end %>
|
7
9
|
|
8
10
|
<%= content %>
|
9
11
|
<% if name.present? %></turbo-frame><% end %>
|
@@ -24,7 +24,7 @@ module Avo
|
|
24
24
|
rescue_from Pundit::NotAuthorizedError, with: :render_unauthorized
|
25
25
|
rescue_from ActiveRecord::RecordInvalid, with: :exception_logger
|
26
26
|
|
27
|
-
helper_method :_current_user, :resources_path, :resource_path, :new_resource_path, :edit_resource_path, :resource_attach_path, :resource_detach_path, :related_resources_path
|
27
|
+
helper_method :_current_user, :resources_path, :resource_path, :new_resource_path, :edit_resource_path, :resource_attach_path, :resource_detach_path, :related_resources_path, :turbo_frame_request?
|
28
28
|
add_flash_types :info, :warning, :success, :error
|
29
29
|
|
30
30
|
def init_app
|
@@ -79,6 +79,12 @@ module Avo
|
|
79
79
|
instance_eval(&Avo.configuration.context)
|
80
80
|
end
|
81
81
|
|
82
|
+
# This is coming from Turbo::Frames::FrameRequest module.
|
83
|
+
# Exposing it as public method
|
84
|
+
def turbo_frame_request?
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
82
88
|
private
|
83
89
|
|
84
90
|
def set_resource_name
|
@@ -5,7 +5,7 @@ module Avo
|
|
5
5
|
before_action :set_resource_name
|
6
6
|
before_action :set_resource
|
7
7
|
before_action :hydrate_resource
|
8
|
-
before_action :set_model, only: [:show, :edit, :destroy, :update]
|
8
|
+
before_action :set_model, only: [:show, :edit, :destroy, :update, :order]
|
9
9
|
before_action :set_model_to_fill
|
10
10
|
before_action :fill_model, only: [:create, :update]
|
11
11
|
before_action :authorize_action
|
@@ -190,6 +190,19 @@ module Avo
|
|
190
190
|
end
|
191
191
|
end
|
192
192
|
|
193
|
+
def order
|
194
|
+
direction = params[:direction].to_sym
|
195
|
+
order_actions = @resource.class.order_actions
|
196
|
+
|
197
|
+
if direction.present? && order_actions[direction].present?
|
198
|
+
order_actions[direction].call(@model)
|
199
|
+
end
|
200
|
+
|
201
|
+
respond_to do |format|
|
202
|
+
format.html { redirect_to params[:referrer] || resources_path(resource: @resource) }
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
193
206
|
private
|
194
207
|
|
195
208
|
def model_params
|
@@ -73,5 +73,9 @@ module Avo
|
|
73
73
|
|
74
74
|
avo.resources_associations_index_path(@parent_resource.model_class.model_name.route_key, @parent_resource.model.id, **existing_params, **args )
|
75
75
|
end
|
76
|
+
|
77
|
+
def order_up_resource_path(model:, resource:, **args)
|
78
|
+
avo.send :"order_up_resources_#{resource.singular_model_key}_path", model, **args
|
79
|
+
end
|
76
80
|
end
|
77
81
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { Application } from '@hotwired/stimulus'
|
2
|
+
import { Popover } from 'tailwindcss-stimulus-components'
|
2
3
|
|
3
4
|
const application = Application.start()
|
4
5
|
|
@@ -6,4 +7,7 @@ const application = Application.start()
|
|
6
7
|
application.debug = false
|
7
8
|
window.Stimulus = application
|
8
9
|
|
10
|
+
// Register stimulus-components controller
|
11
|
+
application.register('popover', Popover)
|
12
|
+
|
9
13
|
export { application }
|
data/config/routes.rb
CHANGED
@@ -17,6 +17,9 @@ Avo::Engine.routes.draw do
|
|
17
17
|
get "/:resource_name/:id/active_storage_attachments/:attachment_name/:signed_attachment_id", to: "attachments#show"
|
18
18
|
delete "/:resource_name/:id/active_storage_attachments/:attachment_name/:signed_attachment_id", to: "attachments#destroy"
|
19
19
|
|
20
|
+
# Ordering
|
21
|
+
patch "/:resource_name/:id/order", to: "resources#order"
|
22
|
+
|
20
23
|
# Actions
|
21
24
|
get "/:resource_name(/:id)/actions/:action_id", to: "actions#show"
|
22
25
|
post "/:resource_name(/:id)/actions/:action_id", to: "actions#handle"
|
data/lib/avo/base_resource.rb
CHANGED
@@ -36,6 +36,7 @@ module Avo
|
|
36
36
|
class_attribute :unscoped_queries_on_index, default: false
|
37
37
|
class_attribute :resolve_query_scope
|
38
38
|
class_attribute :resolve_find_scope
|
39
|
+
class_attribute :ordering
|
39
40
|
|
40
41
|
class << self
|
41
42
|
def grid(&block)
|
@@ -80,6 +81,12 @@ module Avo
|
|
80
81
|
def authorization
|
81
82
|
Avo::Services::AuthorizationService.new Avo::App.current_user
|
82
83
|
end
|
84
|
+
|
85
|
+
def order_actions
|
86
|
+
return {} if ordering.blank?
|
87
|
+
|
88
|
+
ordering.dig(:actions) || {}
|
89
|
+
end
|
83
90
|
end
|
84
91
|
|
85
92
|
def initialize
|
@@ -135,6 +142,7 @@ module Avo
|
|
135
142
|
# we're matching the reflection inverse_of foriegn key with the field's foreign_key
|
136
143
|
if field.is_a?(Avo::Fields::BelongsToField)
|
137
144
|
if field.respond_to?(:foreign_key) &&
|
145
|
+
reflection.inverse_of.present? &&
|
138
146
|
reflection.inverse_of.foreign_key == field.foreign_key
|
139
147
|
is_valid = false
|
140
148
|
end
|
data/lib/avo/version.rb
CHANGED