avo 1.22.3 → 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/README.md +6 -0
- 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/{views/avo/partials/_alert.html.erb → components/avo/alert_component.html.erb} +0 -0
- data/app/components/avo/alert_component.rb +11 -0
- data/app/components/avo/alerts_component.html.erb +3 -0
- data/app/components/avo/alerts_component.rb +5 -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/navigation_link_component.rb +1 -1
- data/app/components/avo/resource_component.rb +1 -1
- data/app/{views/avo/partials/_turbo_frame_wrap.html.erb → components/avo/turbo_frame_wrapper_component.html.erb} +4 -2
- data/app/components/avo/turbo_frame_wrapper_component.rb +9 -0
- data/app/controllers/avo/application_controller.rb +14 -1
- data/app/controllers/avo/base_controller.rb +14 -2
- data/app/helpers/avo/application_helper.rb +1 -1
- data/app/helpers/avo/url_helpers.rb +4 -0
- data/app/javascript/js/application.js +4 -0
- data/app/javascript/js/controllers/modal_controller.js +9 -0
- data/app/javascript/js/controllers/search_controller.js +6 -1
- data/app/views/avo/actions/show.html.erb +7 -3
- data/app/views/layouts/avo/application.html.erb +1 -1
- data/config/routes.rb +3 -0
- data/lib/avo/base_action.rb +21 -0
- data/lib/avo/base_resource.rb +8 -0
- data/lib/avo/licensing/h_q.rb +55 -1
- 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 +7645 -7375
- data/public/avo-assets/avo.js.map +3 -3
- metadata +19 -5
- data/app/views/avo/partials/_alerts.html.erb +0 -3
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
|
data/README.md
CHANGED
@@ -73,3 +73,9 @@ Please read the [UPGRADE_GUIDE.MD](https://docs.avohq.io/1.0/upgrade.html)
|
|
73
73
|
|
74
74
|
|
75
75
|
![Alt](https://repobeats.axiom.co/api/embed/1481a6a259064f02a7936470d12a50802a9c98a4.svg "Repobeats analytics image")
|
76
|
+
|
77
|
+
# Shoutouts
|
78
|
+
|
79
|
+
[Get a box of waffles and some of the best app monitoring from Appsignal](https://appsignal.com/r/93dbe69bfb) 🧇
|
80
|
+
|
81
|
+
[Get $100 in credits from Digital Ocean](https://www.digitalocean.com/?refcode=efc1fe881d74&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge) 💸
|
@@ -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>
|
File without changes
|
@@ -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>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::NavigationLinkComponent < ViewComponent::Base
|
4
|
-
def initialize(label: nil, path: nil, active: :inclusive, size: :md, target:
|
4
|
+
def initialize(label: nil, path: nil, active: :inclusive, size: :md, target: nil)
|
5
5
|
@label = label
|
6
6
|
@path = path
|
7
7
|
@active = active
|
@@ -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 %>
|
@@ -13,6 +13,7 @@ module Avo
|
|
13
13
|
protect_from_forgery with: :exception
|
14
14
|
before_action :init_app
|
15
15
|
before_action :check_avo_license
|
16
|
+
before_action :set_locale
|
16
17
|
before_action :set_authorization
|
17
18
|
before_action :_authenticate!
|
18
19
|
before_action :set_container_classes
|
@@ -23,7 +24,7 @@ module Avo
|
|
23
24
|
rescue_from Pundit::NotAuthorizedError, with: :render_unauthorized
|
24
25
|
rescue_from ActiveRecord::RecordInvalid, with: :exception_logger
|
25
26
|
|
26
|
-
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?
|
27
28
|
add_flash_types :info, :warning, :success, :error
|
28
29
|
|
29
30
|
def init_app
|
@@ -78,6 +79,12 @@ module Avo
|
|
78
79
|
instance_eval(&Avo.configuration.context)
|
79
80
|
end
|
80
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
|
+
|
81
88
|
private
|
82
89
|
|
83
90
|
def set_resource_name
|
@@ -245,5 +252,11 @@ module Avo
|
|
245
252
|
def model_param_key
|
246
253
|
@resource.form_scope
|
247
254
|
end
|
255
|
+
|
256
|
+
def set_locale
|
257
|
+
I18n.locale = params[:locale] || I18n.default_locale
|
258
|
+
|
259
|
+
I18n.default_locale = I18n.locale
|
260
|
+
end
|
248
261
|
end
|
249
262
|
end
|
@@ -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
|
@@ -84,7 +84,6 @@ module Avo
|
|
84
84
|
def new
|
85
85
|
@model = @resource.model_class.new
|
86
86
|
@resource = @resource.hydrate(model: @model, view: :new, user: _current_user)
|
87
|
-
# abort @model.course.inspect
|
88
87
|
|
89
88
|
@page_title = @resource.default_panel_name
|
90
89
|
add_breadcrumb resource_name.humanize, resources_path(resource: @resource)
|
@@ -191,6 +190,19 @@ module Avo
|
|
191
190
|
end
|
192
191
|
end
|
193
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
|
+
|
194
206
|
private
|
195
207
|
|
196
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 }
|
@@ -8,4 +8,13 @@ export default class extends Controller {
|
|
8
8
|
|
9
9
|
document.dispatchEvent(new Event('actions-modal:close'))
|
10
10
|
}
|
11
|
+
|
12
|
+
delayedClose() {
|
13
|
+
const vm = this
|
14
|
+
|
15
|
+
setTimeout(() => {
|
16
|
+
vm.modalTarget.remove()
|
17
|
+
document.dispatchEvent(new Event('actions-modal:close'))
|
18
|
+
}, 500)
|
19
|
+
}
|
11
20
|
}
|
@@ -177,11 +177,16 @@ export default class extends Controller {
|
|
177
177
|
openOnFocus: true,
|
178
178
|
detachedMediaQuery: '',
|
179
179
|
getSources: ({ query }) => {
|
180
|
+
document.body.classList.add('search-loading')
|
180
181
|
const endpoint = that.searchUrl(query)
|
181
182
|
|
182
183
|
return that
|
183
184
|
.debouncedFetch(endpoint)
|
184
|
-
.then((response) =>
|
185
|
+
.then((response) => {
|
186
|
+
document.body.classList.remove('search-loading')
|
187
|
+
|
188
|
+
return response.json()
|
189
|
+
})
|
185
190
|
.then((data) => Object.keys(data).map((resourceName) => that.addSource(resourceName, data[resourceName])))
|
186
191
|
},
|
187
192
|
})
|
@@ -7,7 +7,11 @@
|
|
7
7
|
data-resource-id="<%= params[:id] %>"
|
8
8
|
class="hidden text-slate-800"
|
9
9
|
>
|
10
|
-
<%= form_with model: @model,
|
10
|
+
<%= form_with model: @model,
|
11
|
+
scope: 'fields',
|
12
|
+
url: "#{@resource.records_path}/actions/#{@action.param_id}",
|
13
|
+
data: @action.class.form_data_attributes do |form|
|
14
|
+
%>
|
11
15
|
<%= render Avo::ModalComponent.new do |c| %>
|
12
16
|
<% c.heading do %>
|
13
17
|
<%= @action.action_name %>
|
@@ -26,8 +30,8 @@
|
|
26
30
|
<% end %>
|
27
31
|
|
28
32
|
<% c.controls do %>
|
29
|
-
<%= a_button @action.cancel_button_label,
|
30
|
-
<%= a_button @action.confirm_button_label, type: :submit, color: :green, size: :sm %>
|
33
|
+
<%= a_button @action.cancel_button_label, data: { action: 'click->modal#close' }, size: :sm %>
|
34
|
+
<%= a_button @action.confirm_button_label, type: :submit, color: :green, size: :sm, data: @action.class.submit_button_data_attributes %>
|
31
35
|
<% end %>
|
32
36
|
<% end %>
|
33
37
|
<% end %>
|
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_action.rb
CHANGED
@@ -15,6 +15,7 @@ module Avo
|
|
15
15
|
class_attribute :fields
|
16
16
|
class_attribute :standalone, default: false
|
17
17
|
class_attribute :visible
|
18
|
+
class_attribute :may_download_file, default: false
|
18
19
|
|
19
20
|
attr_accessor :response
|
20
21
|
attr_accessor :model
|
@@ -22,6 +23,26 @@ module Avo
|
|
22
23
|
attr_accessor :user
|
23
24
|
attr_accessor :fields_loader
|
24
25
|
|
26
|
+
class << self
|
27
|
+
def form_data_attributes
|
28
|
+
# We can't respond with a file download from Turbo se we disable it on the form
|
29
|
+
if may_download_file
|
30
|
+
{ 'turbo': false }
|
31
|
+
else
|
32
|
+
{ 'turbo-frame': '_top', 'action-target': 'form' }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# We can't respond with a file download from Turbo se we disable close the modal manually after a while (it's a hack, we know)
|
37
|
+
def submit_button_data_attributes
|
38
|
+
if may_download_file
|
39
|
+
{ action: 'click->modal#delayedClose' }
|
40
|
+
else
|
41
|
+
{}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
25
46
|
def action_name
|
26
47
|
return name if name.present?
|
27
48
|
|
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
|