avo 1.23.0 → 1.24.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 +6 -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 +35 -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 +11 -0
- data/app/components/avo/index/ordering/button_component.rb +37 -0
- data/app/components/avo/index/ordering/buttons_component.html.erb +32 -0
- data/app/components/avo/index/ordering/buttons_component.rb +45 -0
- data/app/components/avo/index/resource_controls_component.html.erb +9 -4
- data/app/components/avo/index/resource_controls_component.rb +2 -1
- data/app/components/avo/index/table_row_component.html.erb +1 -1
- data/app/components/avo/resource_component.rb +1 -22
- 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 +16 -1
- data/app/controllers/avo/relations_controller.rb +15 -8
- data/app/helpers/avo/url_helpers.rb +4 -0
- data/app/javascript/js/application.js +4 -0
- data/avo.gemspec +1 -0
- data/config/routes.rb +4 -0
- data/lib/avo/base_resource.rb +13 -0
- data/lib/avo/hosts/ordering.rb +22 -0
- data/lib/avo/licensing/pro_license.rb +1 -0
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/locales/avo.en.yml +6 -0
- 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 +28 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4990a8b947c8086e635f9a4efedf7b58692ffbeebcd7bbc5ee002f8526a0e1fc
|
4
|
+
data.tar.gz: 80f48c2eaf8dbe17271afbb64dfb07e3c7b2710371dd049d293981ed0ddf2cb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53cdb462a0b8dbb76060ab440760115b309c05d16dbbde23108811b1b369eeb4a59763d908ff4f5466fe15596f35427817443c146994d9c4466cb2955cdbb6e0
|
7
|
+
data.tar.gz: 83afde6824181a8354d20fb8d9197734abc3d162200625731a47f2adf17501f43f1d08abf897f3e60fbe01960893d2ad71ef2ba4fee540b2c4f943859199eb2a
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (1.
|
4
|
+
avo (1.24.2)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
8
8
|
countries
|
9
|
+
dry-initializer
|
9
10
|
hotwire-rails
|
10
11
|
httparty
|
11
12
|
image_processing
|
@@ -81,6 +82,8 @@ GEM
|
|
81
82
|
minitest (>= 5.1)
|
82
83
|
tzinfo (~> 2.0)
|
83
84
|
zeitwerk (~> 2.3)
|
85
|
+
acts_as_list (1.0.4)
|
86
|
+
activerecord (>= 4.2)
|
84
87
|
addressable (2.8.0)
|
85
88
|
public_suffix (>= 2.0.2, < 5.0)
|
86
89
|
ap (0.1.1)
|
@@ -153,6 +156,7 @@ GEM
|
|
153
156
|
dotenv-rails (2.7.6)
|
154
157
|
dotenv (= 2.7.6)
|
155
158
|
railties (>= 3.2)
|
159
|
+
dry-initializer (3.1.1)
|
156
160
|
erubi (1.10.0)
|
157
161
|
factory_bot (6.2.0)
|
158
162
|
activesupport (>= 5.0.0)
|
@@ -397,6 +401,7 @@ PLATFORMS
|
|
397
401
|
|
398
402
|
DEPENDENCIES
|
399
403
|
active_link_to
|
404
|
+
acts_as_list
|
400
405
|
addressable
|
401
406
|
ap
|
402
407
|
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>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Avo::BaseComponent < ViewComponent::Base
|
4
|
+
def has_with_trial(ability)
|
5
|
+
::Avo::App.license.has_with_trial(ability)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
# Figure out what is the corresponding field for this @reflection
|
11
|
+
def field
|
12
|
+
fields = ::Avo::App.get_resource_by_model_name(@reflection.active_record.name).get_field_definitions
|
13
|
+
fields.find { |f| f.id == @reflection.name }
|
14
|
+
rescue
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def relation_resource
|
19
|
+
::Avo::App.get_resource_by_model_name params[:via_resource_class].safe_constantize
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get the resource for the resource using the klass attribute so we get the namespace too
|
23
|
+
def reflection_resource
|
24
|
+
::Avo::App.get_resource_by_model_name(@reflection.klass.to_s)
|
25
|
+
rescue
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get the resource for the resource using the klass attribute so we get the namespace too
|
30
|
+
def reflection_parent_resource
|
31
|
+
::Avo::App.get_resource_by_model_name(@reflection.active_record.to_s)
|
32
|
+
rescue
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
@@ -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,11 @@
|
|
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
|
+
'turbo-frame': params[:turbo_frame],
|
8
|
+
'tippy': 'tooltip',
|
9
|
+
} do %>
|
10
|
+
<%= helpers.svg(svg, class: 'text-gray-400 h-6 hover:text-gray-600') %>
|
11
|
+
<% end %>
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Avo::Index::Ordering::ButtonComponent < Avo::Index::Ordering::BaseComponent
|
4
|
+
attr_accessor :resource
|
5
|
+
attr_accessor :reflection
|
6
|
+
attr_accessor :direction
|
7
|
+
attr_accessor :svg
|
8
|
+
|
9
|
+
def initialize(resource:, direction:, svg: nil, reflection: nil)
|
10
|
+
@resource = resource
|
11
|
+
@reflection = reflection
|
12
|
+
@direction = direction
|
13
|
+
@svg = svg
|
14
|
+
end
|
15
|
+
|
16
|
+
def render?
|
17
|
+
order_actions[direction].present?
|
18
|
+
end
|
19
|
+
|
20
|
+
def order_path(args)
|
21
|
+
if reflection.present?
|
22
|
+
path = "#{::Avo::App.root_path}/resources/#{reflection_parent_resource.route_key}/#{params[:id]}/#{field.id}/#{resource.model.id}/order"
|
23
|
+
else
|
24
|
+
path = "#{::Avo::App.root_path}/resources/#{resource.route_key}/#{resource.model.id}/order"
|
25
|
+
end
|
26
|
+
|
27
|
+
if args.present?
|
28
|
+
string_args = args.map do |key, value|
|
29
|
+
"#{key}=#{value}"
|
30
|
+
end.join('&')
|
31
|
+
|
32
|
+
path = "#{path}?#{string_args}"
|
33
|
+
end
|
34
|
+
|
35
|
+
path
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<div class="flex items-center justify-center">
|
2
|
+
<% if display_inline? %>
|
3
|
+
<div class="flex max-w-xs rounded">
|
4
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :higher, svg: 'arrow-up' %>
|
5
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :lower, svg: 'arrow-down' %>
|
6
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :to_top, svg: 'download-solid-reversed' %>
|
7
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :to_bottom, svg: 'download-solid' %>
|
8
|
+
</div>
|
9
|
+
<% else %>
|
10
|
+
<div class="popover inline-block"
|
11
|
+
data-controller="popover"
|
12
|
+
data-popover-translate-x="-100%"
|
13
|
+
data-popover-translate-y="-32px"
|
14
|
+
data-action="mouseover->popover#mouseOver mouseout->popover#mouseOut"
|
15
|
+
>
|
16
|
+
<%= button_tag nil,
|
17
|
+
title: t('avo.order.reorder_record').capitalize,
|
18
|
+
class: 'flex items-center',
|
19
|
+
data: {
|
20
|
+
'tippy': 'tooltip',
|
21
|
+
} do
|
22
|
+
%>
|
23
|
+
<%= helpers.svg('switch-vertical', class: 'text-gray-400 h-6 hover:text-gray-600') %>
|
24
|
+
<% end %>
|
25
|
+
<div class="flex hidden absolute max-w-xs bg-white rounded p-2 z-40" data-popover-target="content">
|
26
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :higher, svg: 'arrow-up' %>
|
27
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :lower, svg: 'arrow-down' %>
|
28
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :to_top, svg: 'download-solid-reversed' %>
|
29
|
+
<%= render Avo::Index::Ordering::ButtonComponent.new resource: @resource, reflection: @reflection, direction: :to_bottom, svg: 'download-solid' %>
|
30
|
+
</div>
|
31
|
+
<% end %>
|
32
|
+
</div>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Avo::Index::Ordering::ButtonsComponent < Avo::Index::Ordering::BaseComponent
|
4
|
+
def initialize(resource: nil, reflection: nil, view_type: nil)
|
5
|
+
@resource = resource
|
6
|
+
@reflection = reflection
|
7
|
+
@view_type = view_type
|
8
|
+
end
|
9
|
+
|
10
|
+
def render?
|
11
|
+
has_with_trial(:resource_ordering) && can_order_any? && view_type_is_table? && enabled_in_view?
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def can_order_any?
|
17
|
+
order_actions.present?
|
18
|
+
end
|
19
|
+
|
20
|
+
def view_type_is_table?
|
21
|
+
@view_type.to_sym == :table
|
22
|
+
end
|
23
|
+
|
24
|
+
def display_inline?
|
25
|
+
ordering[:display_inline]
|
26
|
+
end
|
27
|
+
|
28
|
+
def enabled_in_view?
|
29
|
+
in_association = @reflection.present?
|
30
|
+
|
31
|
+
if in_association
|
32
|
+
visible_on_option.include? :association
|
33
|
+
else
|
34
|
+
visible_on_option.include? :index
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def visible_on_option
|
39
|
+
[ordering[:visible_on]].flatten
|
40
|
+
end
|
41
|
+
|
42
|
+
def ordering
|
43
|
+
@resource.class.ordering
|
44
|
+
end
|
45
|
+
end
|
@@ -1,14 +1,16 @@
|
|
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
|
+
<%= render Avo::Index::Ordering::ButtonsComponent.new resource: @resource, reflection: @reflection, view_type: @view_type %>
|
3
|
+
|
2
4
|
<% if can_view? %>
|
3
5
|
<%= link_to helpers.svg('eye', class: 'text-gray-400 h-6 hover:text-gray-600'),
|
4
6
|
show_path,
|
5
|
-
title: t('avo.view_item',
|
7
|
+
title: t('avo.view_item', item: singular_resource_name).capitalize,
|
6
8
|
data: {
|
7
9
|
target: 'control:view',
|
8
10
|
control: :show,
|
9
11
|
'tippy': 'tooltip',
|
10
12
|
}
|
11
|
-
|
13
|
+
%>
|
12
14
|
<% end %>
|
13
15
|
|
14
16
|
<% if can_edit? %>
|
@@ -45,7 +47,10 @@
|
|
45
47
|
<% end %>
|
46
48
|
|
47
49
|
<% if can_delete? %>
|
48
|
-
<%= form_with url: helpers.resource_path(model: @resource.model, resource: @resource),
|
50
|
+
<%= form_with url: helpers.resource_path(model: @resource.model, resource: @resource),
|
51
|
+
method: :delete,
|
52
|
+
class: 'flex items-center',
|
53
|
+
html: {
|
49
54
|
'data-turbo-frame': params[:turbo_frame]
|
50
55
|
} do |form| %>
|
51
56
|
<%= 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?
|
@@ -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>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Avo::ResourceComponent <
|
1
|
+
class Avo::ResourceComponent < Avo::BaseComponent
|
2
2
|
def can_create?
|
3
3
|
return authorize_association_for(:create) if @reflection.present?
|
4
4
|
|
@@ -30,25 +30,4 @@ class Avo::ResourceComponent < ViewComponent::Base
|
|
30
30
|
|
31
31
|
association_policy
|
32
32
|
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
# Figure out what is the corresponding field for this @reflection
|
37
|
-
def field
|
38
|
-
fields = ::Avo::App.get_resource_by_model_name(@reflection.active_record.name).get_field_definitions
|
39
|
-
fields.find { |f| f.id == @reflection.name }
|
40
|
-
rescue
|
41
|
-
nil
|
42
|
-
end
|
43
|
-
|
44
|
-
def relation_resource
|
45
|
-
::Avo::App.get_resource_by_model_name params[:via_resource_class].safe_constantize
|
46
|
-
end
|
47
|
-
|
48
|
-
# Get the resource for the resource using the klass attribute so we get the namespace too
|
49
|
-
def reflection_resource
|
50
|
-
::Avo::App.get_resource_by_model_name(@reflection.klass.to_s)
|
51
|
-
rescue
|
52
|
-
nil
|
53
|
-
end
|
54
33
|
end
|
@@ -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,21 @@ module Avo
|
|
190
190
|
end
|
191
191
|
end
|
192
192
|
|
193
|
+
def order
|
194
|
+
direction = params[:direction].to_sym
|
195
|
+
|
196
|
+
if direction.present?
|
197
|
+
@resource
|
198
|
+
.hydrate(model: @model, params: params)
|
199
|
+
.ordering_host
|
200
|
+
.order direction
|
201
|
+
end
|
202
|
+
|
203
|
+
respond_to do |format|
|
204
|
+
format.html { redirect_to params[:referrer] || resources_path(resource: @resource) }
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
193
208
|
private
|
194
209
|
|
195
210
|
def model_params
|
@@ -2,15 +2,15 @@ require_dependency "avo/base_controller"
|
|
2
2
|
|
3
3
|
module Avo
|
4
4
|
class RelationsController < BaseController
|
5
|
-
before_action :set_model, only: [:show, :index, :new, :create, :destroy]
|
5
|
+
before_action :set_model, only: [:show, :index, :new, :create, :destroy, :order]
|
6
6
|
before_action :set_related_resource_name
|
7
|
-
before_action :set_related_resource, only: [:show, :index, :new, :create, :destroy]
|
8
|
-
before_action :hydrate_related_resource, only: [:show, :index, :new, :create, :destroy]
|
9
|
-
before_action :set_related_model, only: [:show]
|
10
|
-
before_action :set_attachment_class, only: [:show, :index, :new, :create, :destroy]
|
11
|
-
before_action :set_attachment_resource, only: [:show, :index, :new, :create, :destroy]
|
12
|
-
before_action :set_attachment_model, only: [:create, :destroy]
|
13
|
-
before_action :set_reflection, only: [:index, :show]
|
7
|
+
before_action :set_related_resource, only: [:show, :index, :new, :create, :destroy, :order]
|
8
|
+
before_action :hydrate_related_resource, only: [:show, :index, :new, :create, :destroy, :order]
|
9
|
+
before_action :set_related_model, only: [:show, :order]
|
10
|
+
before_action :set_attachment_class, only: [:show, :index, :new, :create, :destroy, :order]
|
11
|
+
before_action :set_attachment_resource, only: [:show, :index, :new, :create, :destroy, :order]
|
12
|
+
before_action :set_attachment_model, only: [:create, :destroy, :order]
|
13
|
+
before_action :set_reflection, only: [:index, :show, :order]
|
14
14
|
|
15
15
|
def index
|
16
16
|
@parent_resource = @resource.dup
|
@@ -71,6 +71,13 @@ module Avo
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
def order
|
75
|
+
@parent_resource = @resource.dup
|
76
|
+
@resource, @model = @related_resource, @related_model
|
77
|
+
|
78
|
+
super
|
79
|
+
end
|
80
|
+
|
74
81
|
private
|
75
82
|
|
76
83
|
def set_attachment_class
|
@@ -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/avo.gemspec
CHANGED
data/config/routes.rb
CHANGED
@@ -17,6 +17,10 @@ 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
|
+
patch "/:resource_name/:id/:related_name/:related_id/order", to: "relations#order", as: "associations_order"
|
23
|
+
|
20
24
|
# Actions
|
21
25
|
get "/:resource_name(/:id)/actions/:action_id", to: "actions#show"
|
22
26
|
post "/:resource_name(/:id)/actions/:action_id", to: "actions#handle"
|
data/lib/avo/base_resource.rb
CHANGED
@@ -14,6 +14,7 @@ module Avo
|
|
14
14
|
|
15
15
|
attr_accessor :view
|
16
16
|
attr_accessor :model
|
17
|
+
attr_accessor :reflection
|
17
18
|
attr_accessor :user
|
18
19
|
attr_accessor :params
|
19
20
|
|
@@ -36,6 +37,7 @@ module Avo
|
|
36
37
|
class_attribute :unscoped_queries_on_index, default: false
|
37
38
|
class_attribute :resolve_query_scope
|
38
39
|
class_attribute :resolve_find_scope
|
40
|
+
class_attribute :ordering
|
39
41
|
|
40
42
|
class << self
|
41
43
|
def grid(&block)
|
@@ -80,6 +82,12 @@ module Avo
|
|
80
82
|
def authorization
|
81
83
|
Avo::Services::AuthorizationService.new Avo::App.current_user
|
82
84
|
end
|
85
|
+
|
86
|
+
def order_actions
|
87
|
+
return {} if ordering.blank?
|
88
|
+
|
89
|
+
ordering.dig(:actions) || {}
|
90
|
+
end
|
83
91
|
end
|
84
92
|
|
85
93
|
def initialize
|
@@ -135,6 +143,7 @@ module Avo
|
|
135
143
|
# we're matching the reflection inverse_of foriegn key with the field's foreign_key
|
136
144
|
if field.is_a?(Avo::Fields::BelongsToField)
|
137
145
|
if field.respond_to?(:foreign_key) &&
|
146
|
+
reflection.inverse_of.present? &&
|
138
147
|
reflection.inverse_of.foreign_key == field.foreign_key
|
139
148
|
is_valid = false
|
140
149
|
end
|
@@ -469,5 +478,9 @@ module Avo
|
|
469
478
|
def form_scope
|
470
479
|
model_class.base_class.to_s.underscore.downcase
|
471
480
|
end
|
481
|
+
|
482
|
+
def ordering_host(**args)
|
483
|
+
Avo::Hosts::Ordering.new resource: self, options: self.class.ordering, **args
|
484
|
+
end
|
472
485
|
end
|
473
486
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'dry-initializer'
|
2
|
+
|
3
|
+
module Avo
|
4
|
+
module Hosts
|
5
|
+
class Ordering
|
6
|
+
extend Dry::Initializer
|
7
|
+
|
8
|
+
option :options, default: proc { {} }
|
9
|
+
option :resource
|
10
|
+
option :record, default: proc { resource.model }
|
11
|
+
option :params, default: proc { resource.params }
|
12
|
+
|
13
|
+
def order(direction)
|
14
|
+
action = options.dig(:actions, direction.to_sym)
|
15
|
+
|
16
|
+
if action.present?
|
17
|
+
instance_exec(&action)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/avo/version.rb
CHANGED
@@ -95,3 +95,9 @@ en:
|
|
95
95
|
was_successfully_updated: 'was successfully updated'
|
96
96
|
clear_value: "Clear value"
|
97
97
|
tools: Tools
|
98
|
+
order:
|
99
|
+
reorder_record: Reorder record
|
100
|
+
higher: Move record higher
|
101
|
+
lower: Move record lower
|
102
|
+
to_top: Move record to top
|
103
|
+
to_bottom: Move record to bottom
|