pg_rails 7.6.16 → 7.6.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/pg_associable/app/javascript/modal_controller.js +17 -1
- data/pg_engine/app/assets/stylesheets/pg_rails_b5.scss +8 -1
- data/pg_engine/app/components/inline_edit/inline_show_component.html.slim +2 -1
- data/pg_engine/app/components/search_bar_toggler_component.html.slim +5 -3
- data/pg_engine/app/controllers/admin/accounts_controller.rb +0 -4
- data/pg_engine/app/controllers/admin/email_logs_controller.rb +0 -4
- data/pg_engine/app/controllers/admin/emails_controller.rb +0 -4
- data/pg_engine/app/controllers/admin/simple_user_notifiers_controller.rb +8 -9
- data/pg_engine/app/controllers/admin/user_accounts_controller.rb +0 -4
- data/pg_engine/app/controllers/admin/users_controller.rb +0 -4
- data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +121 -41
- data/pg_engine/app/controllers/public/mensaje_contactos_controller.rb +0 -4
- data/pg_engine/app/controllers/users/accounts_controller.rb +0 -4
- data/pg_engine/app/decorators/pg_engine/base_record_decorator.rb +39 -13
- data/pg_engine/app/helpers/pg_engine/index_helper.rb +17 -3
- data/pg_engine/app/helpers/pg_engine/route_helper.rb +4 -0
- data/pg_engine/app/lib/pg_engine/filtros_builder.rb +7 -9
- data/pg_engine/app/models/account.rb +2 -0
- data/pg_engine/app/models/concerns/pg_engine/naming.rb +55 -0
- data/pg_engine/app/models/pg_engine/base_record.rb +2 -46
- data/pg_engine/app/models/user.rb +1 -1
- data/pg_engine/app/notifiers/simple_user_notifier.rb +4 -0
- data/pg_engine/app/policies/account_policy.rb +9 -9
- data/pg_engine/app/policies/pg_engine/base_policy.rb +15 -3
- data/pg_engine/app/views/admin/accounts/show.html.slim +0 -7
- data/pg_engine/app/views/admin/email_logs/show.html.slim +0 -7
- data/pg_engine/app/views/admin/emails/show.html.slim +0 -7
- data/pg_engine/app/views/admin/simple_user_notifiers/_form.html.slim +1 -1
- data/pg_engine/app/views/admin/simple_user_notifiers/show.html.slim +0 -5
- data/pg_engine/app/views/admin/user_accounts/show.html.slim +0 -7
- data/pg_engine/app/views/admin/users/show.html.slim +1 -5
- data/pg_engine/app/views/pg_engine/base/index.html.slim +39 -14
- data/pg_engine/config/locales/es.rb +42 -0
- data/pg_engine/config/locales/es.yml +1 -6
- data/pg_engine/lib/pg_engine/engine.rb +4 -0
- data/pg_engine/lib/pg_engine/route_helpers.rb +5 -0
- data/pg_engine/spec/controllers/admin/accounts_controller_spec.rb +4 -9
- data/pg_engine/spec/controllers/admin/email_logs_controller_spec.rb +4 -4
- data/pg_engine/spec/controllers/admin/emails_controller_spec.rb +4 -4
- data/pg_engine/spec/controllers/admin/user_accounts_controller_spec.rb +4 -4
- data/pg_engine/spec/controllers/admin/users_controller_spec.rb +4 -9
- data/pg_engine/spec/models/pg_engine/base_record_spec.rb +12 -0
- data/pg_engine/spec/requests/admin/eventos_spec.rb +9 -15
- data/pg_engine/spec/requests/resource_spec.rb +84 -0
- data/pg_engine/spec/requests/users/switcher_spec.rb +2 -2
- data/pg_engine/spec/system/breadcrumbs_spec.rb +9 -21
- data/pg_engine/spec/system/destroy_spec.rb +3 -3
- data/pg_engine/spec/system/login_spec.rb +1 -1
- data/pg_engine/spec/system/modal_windows_spec.rb +5 -5
- data/pg_engine/spec/system/tenants_spec.rb +2 -2
- data/pg_layout/app/javascript/application.js +4 -2
- data/pg_layout/app/javascript/controllers/embedded_frame_controller.js +4 -0
- data/pg_layout/app/views/layouts/pg_layout/base.html.slim +1 -0
- data/pg_layout/app/views/layouts/pg_layout/show.html.slim +10 -0
- data/pg_rails/lib/version.rb +1 -1
- data/pg_scaffold/lib/generators/pg_rspec/scaffold/templates/controller_spec.rb +4 -11
- data/pg_scaffold/lib/generators/pg_scaffold/templates/controller.rb +1 -5
- data/pg_scaffold/lib/generators/pg_slim/templates/show.html.slim +0 -7
- metadata +6 -3
- data/pg_engine/app/components/actions_component.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: deedeb8e6184e2e6771a5328b7f11f6d63caf6ac12e227f484a2d5c71034bd0c
|
4
|
+
data.tar.gz: 06d81a222b43e8e5d3c84f833e004a1c6566cf67729b6c42fea8c6ed71edde8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c4023d8e7b9e7d951882f9ac21550f898a9ec9c8da183d38b8b09d5052f4de2e4c02c67673251330698e188cb5e80aefd9a127bcaf861a642720eed8329e656
|
7
|
+
data.tar.gz: a049bcc3f480d9876bac44280b6a45d52ad2896c24f49c37cdc3b0bb45842f05c18cfbd5fc126cd0b43f017469b9376246c224a15ed37ab691764c264945d493
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
2
2
|
import * as bootstrap from 'bootstrap'
|
3
|
+
import { Rollbar } from 'rollbar'
|
3
4
|
|
4
5
|
export default class extends Controller {
|
5
6
|
static outlets = ['asociable']
|
@@ -41,7 +42,13 @@ export default class extends Controller {
|
|
41
42
|
this.reloadTop()
|
42
43
|
ev.stopPropagation()
|
43
44
|
} else {
|
44
|
-
|
45
|
+
if (ev.data.dataset.reload) {
|
46
|
+
this.reload()
|
47
|
+
this.reloadTop()
|
48
|
+
ev.stopPropagation()
|
49
|
+
} else {
|
50
|
+
this.back(ev)
|
51
|
+
}
|
45
52
|
}
|
46
53
|
})
|
47
54
|
|
@@ -73,6 +80,15 @@ export default class extends Controller {
|
|
73
80
|
}
|
74
81
|
}
|
75
82
|
|
83
|
+
reload () {
|
84
|
+
const frame = this.element.querySelector('turbo-frame')
|
85
|
+
if (frame.attributes.src) {
|
86
|
+
frame.reload()
|
87
|
+
} else {
|
88
|
+
Rollbar.error('Modal without frame')
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
76
92
|
reloadTop () {
|
77
93
|
// FIXME: rename to main?
|
78
94
|
const topFrame = document.querySelector('#top')
|
@@ -71,11 +71,18 @@ input[type=datetime-local], input[type=datetime] {
|
|
71
71
|
.listado {
|
72
72
|
td, th {
|
73
73
|
padding: 0.25rem 1rem;
|
74
|
+
|
75
|
+
&:has(.actions-wrapper) {
|
76
|
+
width: 0.1%;
|
77
|
+
border-right: 1px solid #c1c1c1;
|
78
|
+
padding: 0 1rem;
|
79
|
+
vertical-align: middle;
|
80
|
+
}
|
74
81
|
}
|
75
82
|
}
|
76
83
|
.listado .actions-wrapper {
|
77
84
|
display: flex;
|
78
|
-
justify-content: flex-end;
|
85
|
+
// justify-content: flex-end;
|
79
86
|
gap: 4px;
|
80
87
|
|
81
88
|
.btn-sm {
|
@@ -1,4 +1,5 @@
|
|
1
|
-
- if
|
1
|
+
- if Current.namespace == :users && \
|
2
|
+
@model.class.inline_editable?(@unsuffixed_attribute) && helpers.policy(@model).edit?
|
2
3
|
= helpers.turbo_frame_tag(@frame_id, class: 'inline-edit')
|
3
4
|
- if @record_updated
|
4
5
|
pg-event[data-event-name="pg:record-updated" data-inline="true" data-turbo-temporary=""
|
@@ -1,8 +1,10 @@
|
|
1
1
|
- if helpers.show_filters?
|
2
2
|
= link_to url_for(ocultar_filtros: 1, cancel_filter: 'true'),
|
3
|
-
class: '
|
3
|
+
class: 'dropdown-item icon-link' do
|
4
|
+
i.bi.bi-funnel-fill.lh-1
|
4
5
|
| Ocultar filtros
|
5
6
|
- else
|
6
7
|
= link_to url_for(mostrar_filtros: 1),
|
7
|
-
class: '
|
8
|
-
|
8
|
+
class: 'dropdown-item icon-link' do
|
9
|
+
i.bi.bi-funnel-fill.lh-1
|
10
|
+
| Mostrar filtros
|
@@ -8,10 +8,6 @@ module Admin
|
|
8
8
|
|
9
9
|
self.clase_modelo = EmailLog
|
10
10
|
|
11
|
-
before_action(only: :index) { authorize EmailLog }
|
12
|
-
|
13
|
-
before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
|
14
|
-
|
15
11
|
before_action do
|
16
12
|
@actions = [
|
17
13
|
["Mailgun sync: #{ENV.fetch('MAILGUN_DOMAIN', nil)}", mailgun_sync_admin_email_logs_path, {
|
@@ -8,10 +8,6 @@ module Admin
|
|
8
8
|
|
9
9
|
self.clase_modelo = Email
|
10
10
|
|
11
|
-
before_action(only: :index) { authorize Email }
|
12
|
-
|
13
|
-
before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
|
14
|
-
|
15
11
|
after_action only: :create do
|
16
12
|
if @saved
|
17
13
|
PgEngine::AdminMailer.with(email_object: @email).admin_mail.deliver_later
|
@@ -4,8 +4,6 @@ module Admin
|
|
4
4
|
|
5
5
|
self.clase_modelo = SimpleUserNotifier
|
6
6
|
|
7
|
-
before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
|
8
|
-
|
9
7
|
def column_options_for(object, attribute)
|
10
8
|
case attribute
|
11
9
|
when :message
|
@@ -17,25 +15,25 @@ module Admin
|
|
17
15
|
|
18
16
|
# rubocop:disable Metrics/MethodLength
|
19
17
|
def create
|
20
|
-
@
|
21
|
-
# @
|
22
|
-
unless @
|
18
|
+
@simple_user_notifier = SimpleUserNotifier.new(modelo_params)
|
19
|
+
# @simple_user_notifier.message.save!
|
20
|
+
unless @simple_user_notifier.valid?
|
23
21
|
render :new, status: :unprocessable_entity
|
24
22
|
return
|
25
23
|
end
|
26
24
|
json_params_for_event = {
|
27
|
-
message: @
|
28
|
-
tooltip: @
|
25
|
+
message: @simple_user_notifier.message,
|
26
|
+
tooltip: @simple_user_notifier.tooltip
|
29
27
|
}
|
30
28
|
notifier = SimpleUserNotifier.with(json_params_for_event)
|
31
29
|
|
32
|
-
case @
|
30
|
+
case @simple_user_notifier.target
|
33
31
|
when 'todos'
|
34
32
|
notifier.deliver(User.all)
|
35
33
|
when 'devs'
|
36
34
|
notifier.deliver(User.where(developer: true))
|
37
35
|
when 'user_ids'
|
38
|
-
notifier.deliver(User.where(email: @
|
36
|
+
notifier.deliver(User.where(email: @simple_user_notifier.user_ids.split(',')))
|
39
37
|
else
|
40
38
|
# :nocov:
|
41
39
|
'shouldnt happen'
|
@@ -46,6 +44,7 @@ module Admin
|
|
46
44
|
rescue StandardError => e
|
47
45
|
# :nocov:
|
48
46
|
flash.now[:alert] = e.to_s
|
47
|
+
# @simple_user_notifier = @simple_user_notifier.decorate
|
49
48
|
render :new, status: :unprocessable_entity
|
50
49
|
# :nocov:
|
51
50
|
end
|
@@ -10,10 +10,6 @@ module Admin
|
|
10
10
|
self.nested_class = Account
|
11
11
|
self.nested_key = :account_id
|
12
12
|
|
13
|
-
before_action(only: :index) { authorize UserAccount }
|
14
|
-
|
15
|
-
before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
|
16
|
-
|
17
13
|
private
|
18
14
|
|
19
15
|
def atributos_permitidos
|
@@ -8,14 +8,10 @@ module Admin
|
|
8
8
|
|
9
9
|
self.clase_modelo = User
|
10
10
|
|
11
|
-
before_action(only: :index) { authorize User }
|
12
|
-
|
13
11
|
before_action only: %i[update] do
|
14
12
|
params[:user].delete(:password) if params[:user][:password].blank?
|
15
13
|
end
|
16
14
|
|
17
|
-
before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
|
18
|
-
|
19
15
|
def create
|
20
16
|
@user.skip_confirmation!
|
21
17
|
@user.orphan = true
|
@@ -10,6 +10,9 @@ module PgEngine
|
|
10
10
|
# TODO: separar los endpoints de la lógica de filtros para evitar esta variable
|
11
11
|
# en Agenda
|
12
12
|
attr_accessor :skip_default_breadcrumb
|
13
|
+
|
14
|
+
# Skip set_instancia_modelo && authorize
|
15
|
+
attr_accessor :skip_default_hooks
|
13
16
|
end
|
14
17
|
clazz.delegate :nested_key, :nested_class, :clase_modelo, to: clazz
|
15
18
|
|
@@ -22,6 +25,7 @@ module PgEngine
|
|
22
25
|
clazz.helper_method :show_filters?
|
23
26
|
clazz.helper_method :available_page_sizes
|
24
27
|
clazz.helper_method :column_options_for
|
28
|
+
clazz.helper_method :instancia_modelo
|
25
29
|
|
26
30
|
clazz.before_action do
|
27
31
|
# TODO: quitar esto, que se use el attr_accessor
|
@@ -29,6 +33,14 @@ module PgEngine
|
|
29
33
|
@clase_modelo = clase_modelo
|
30
34
|
end
|
31
35
|
|
36
|
+
clazz.before_action(only: %i[index archived], unless: -> { clazz.skip_default_hooks }) do
|
37
|
+
authorize clase_modelo
|
38
|
+
end
|
39
|
+
|
40
|
+
clazz.before_action :set_instancia_modelo,
|
41
|
+
only: %i[new create show edit update destroy archive restore],
|
42
|
+
unless: -> { clazz.skip_default_hooks }
|
43
|
+
|
32
44
|
clazz.before_action unless: -> { clazz.skip_default_breadcrumb } do
|
33
45
|
if nested_record.present?
|
34
46
|
# Link al nested, siempre que sea no sea un embedded frame
|
@@ -40,20 +52,28 @@ module PgEngine
|
|
40
52
|
add_breadcrumb nested_record.decorate.to_s_short
|
41
53
|
else
|
42
54
|
add_breadcrumb nested_record.decorate.to_s_short,
|
43
|
-
nested_record.decorate.target_object
|
55
|
+
path_for(nested_record.decorate.target_object)
|
44
56
|
end
|
45
57
|
end
|
46
58
|
|
47
|
-
|
48
|
-
|
49
|
-
|
59
|
+
if action_name == 'archived'
|
60
|
+
# En el listado de archivados tiene que haber un link al listado
|
61
|
+
# principal
|
62
|
+
add_breadcrumb clase_modelo.nombre_plural,
|
63
|
+
path_for([pg_namespace, nested_record, clase_modelo])
|
64
|
+
else
|
65
|
+
# Texto de index pero sin link, porque se supone que es un
|
66
|
+
# embedded index o es un show dentro de un embedded y por ende
|
67
|
+
# el paso atrás no tiene que ser el listado sino el show del parent
|
68
|
+
add_breadcrumb clase_modelo.nombre_plural
|
69
|
+
end
|
50
70
|
|
51
71
|
elsif !modal_targeted?
|
52
72
|
# Link al index, siempre que no sea un modal, porque en tal
|
53
73
|
# caso se supone que el index está visible en el main frame
|
54
74
|
if clase_modelo.present?
|
55
75
|
add_breadcrumb clase_modelo.nombre_plural,
|
56
|
-
|
76
|
+
path_for([pg_namespace, nested_record, clase_modelo])
|
57
77
|
else
|
58
78
|
# :nocov:
|
59
79
|
pg_warn 'clase_modelo is nil'
|
@@ -113,8 +133,10 @@ module PgEngine
|
|
113
133
|
end
|
114
134
|
|
115
135
|
def set_layout
|
116
|
-
if action_name
|
136
|
+
if action_name.in? %w[index archived]
|
117
137
|
'pg_layout/base'
|
138
|
+
elsif action_name == 'show'
|
139
|
+
'pg_layout/show'
|
118
140
|
else
|
119
141
|
'pg_layout/containerized'
|
120
142
|
end
|
@@ -129,10 +151,20 @@ module PgEngine
|
|
129
151
|
pg_respond_buscar
|
130
152
|
end
|
131
153
|
|
154
|
+
def archived
|
155
|
+
add_breadcrumb 'Archivados'
|
156
|
+
|
157
|
+
@index_url = index_url
|
158
|
+
|
159
|
+
@collection = filtros_y_policy(atributos_para_buscar, 'discarded_at desc', archived: true)
|
160
|
+
|
161
|
+
pg_respond_index(archived: true)
|
162
|
+
end
|
163
|
+
|
132
164
|
def index
|
133
165
|
@collection = filtros_y_policy(atributos_para_buscar, default_sort)
|
134
166
|
|
135
|
-
pg_respond_index
|
167
|
+
pg_respond_index(archived: false)
|
136
168
|
end
|
137
169
|
|
138
170
|
def show
|
@@ -186,12 +218,48 @@ module PgEngine
|
|
186
218
|
end
|
187
219
|
|
188
220
|
def destroy
|
189
|
-
pg_respond_destroy(instancia_modelo, params[:
|
221
|
+
pg_respond_destroy(instancia_modelo, params[:land_on])
|
222
|
+
end
|
223
|
+
|
224
|
+
def archive
|
225
|
+
discard_undiscard(:discard)
|
226
|
+
end
|
227
|
+
|
228
|
+
def restore
|
229
|
+
discard_undiscard(:undiscard)
|
190
230
|
end
|
191
231
|
# End public endpoints
|
192
232
|
|
193
233
|
protected
|
194
234
|
|
235
|
+
def discard_undiscard(method)
|
236
|
+
if instancia_modelo.send(method)
|
237
|
+
if accepts_turbo_stream?
|
238
|
+
body = <<~HTML.html_safe
|
239
|
+
<pg-event data-event-name="pg:record-updated" data-reload="true" data-turbo-temporary>
|
240
|
+
</pg-event>
|
241
|
+
HTML
|
242
|
+
render turbo_stream: turbo_stream.append(current_turbo_frame, body)
|
243
|
+
else
|
244
|
+
redirect_to instancia_modelo.decorate.target_object
|
245
|
+
end
|
246
|
+
|
247
|
+
else
|
248
|
+
message = I18n.t('pg_engine.resource_not_updated', model: instancia_modelo.class)
|
249
|
+
if accepts_turbo_stream?
|
250
|
+
flash.now[:alert] = message
|
251
|
+
render turbo_stream: render_turbo_stream_flash_messages, status: :unprocessable_entity
|
252
|
+
else
|
253
|
+
flash[:alert] = message
|
254
|
+
redirect_to instancia_modelo.decorate.target_object
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def index_url
|
260
|
+
path_for([pg_namespace, nested_record, clase_modelo])
|
261
|
+
end
|
262
|
+
|
195
263
|
def default_sort
|
196
264
|
'id desc'
|
197
265
|
end
|
@@ -309,10 +377,10 @@ module PgEngine
|
|
309
377
|
end
|
310
378
|
end
|
311
379
|
|
312
|
-
def pg_respond_index
|
380
|
+
def pg_respond_index(archived:)
|
313
381
|
respond_to do |format|
|
314
382
|
format.json { render json: @collection }
|
315
|
-
format.html { render_listing }
|
383
|
+
format.html { render_listing(archived:) }
|
316
384
|
format.xlsx do
|
317
385
|
render xlsx: 'download',
|
318
386
|
filename: "#{clase_modelo.nombre_plural.gsub(' ', '-').downcase}" \
|
@@ -331,12 +399,20 @@ module PgEngine
|
|
331
399
|
end
|
332
400
|
end
|
333
401
|
|
334
|
-
def
|
335
|
-
|
402
|
+
def land_on_url(land_on)
|
403
|
+
case land_on
|
404
|
+
when 'index'
|
405
|
+
index_url
|
406
|
+
else
|
407
|
+
# :nocov:
|
408
|
+
pg_warn "Unrecognized land_on: #{land_on}"
|
409
|
+
instancia_modelo.decorate.target_object
|
410
|
+
# :nocov:
|
411
|
+
end
|
336
412
|
end
|
337
413
|
|
338
414
|
# rubocop:disable Metrics/PerceivedComplexity
|
339
|
-
def pg_respond_destroy(model,
|
415
|
+
def pg_respond_destroy(model, land_on = nil)
|
340
416
|
if destroy_model(model)
|
341
417
|
# FIXME: rename to main
|
342
418
|
if turbo_frame? && current_turbo_frame != 'top'
|
@@ -345,8 +421,10 @@ module PgEngine
|
|
345
421
|
</pg-event>
|
346
422
|
HTML
|
347
423
|
render turbo_stream: turbo_stream.append(current_turbo_frame, body)
|
348
|
-
elsif
|
349
|
-
redirect_to
|
424
|
+
elsif land_on.present?
|
425
|
+
redirect_to land_on_url(land_on),
|
426
|
+
notice: I18n.t('pg_engine.resource_destroyed', model: model.class),
|
427
|
+
status: :see_other
|
350
428
|
elsif accepts_turbo_stream?
|
351
429
|
body = <<~HTML.html_safe
|
352
430
|
<pg-event data-event-name="pg:record-destroyed" data-turbo-temporary>
|
@@ -355,7 +433,8 @@ module PgEngine
|
|
355
433
|
render turbo_stream: turbo_stream.append_all('body', body)
|
356
434
|
else
|
357
435
|
redirect_back(fallback_location: root_path,
|
358
|
-
notice:
|
436
|
+
notice: I18n.t('pg_engine.resource_destroyed', model: model.class),
|
437
|
+
status: 303)
|
359
438
|
end
|
360
439
|
elsif in_modal?
|
361
440
|
|
@@ -372,32 +451,31 @@ module PgEngine
|
|
372
451
|
# rubocop:enable Metrics/PerceivedComplexity
|
373
452
|
|
374
453
|
def destroy_model(model)
|
375
|
-
@error_message = '
|
454
|
+
@error_message = I18n.t('pg_engine.resource_not_destroyed', model: model.class)
|
376
455
|
|
377
456
|
begin
|
378
|
-
|
379
|
-
return true if model.send(destroy_method)
|
457
|
+
return true if model.destroy
|
380
458
|
|
381
459
|
@error_message = model.errors.full_messages.join(', ').presence || @error_message
|
382
460
|
|
383
461
|
false
|
384
462
|
rescue ActiveRecord::InvalidForeignKey => e
|
385
|
-
model_name = t("activerecord.models.#{model.class.name.underscore}")
|
386
|
-
@error_message = "#{model_name} no se pudo borrar porque tiene elementos asociados."
|
387
463
|
pg_warn(e)
|
464
|
+
@error_message = I18n.t('pg_engine.resource_not_destroyed_because_associated', model: model.class)
|
388
465
|
end
|
389
466
|
|
390
467
|
false
|
391
468
|
end
|
392
469
|
|
393
|
-
def render_listing
|
470
|
+
def render_listing(archived:)
|
394
471
|
total = @collection.count
|
395
472
|
current_page = params[:page].presence&.to_i || 1
|
396
473
|
if current_page_size * (current_page - 1) >= total
|
397
474
|
current_page = (total.to_f / current_page_size).ceil
|
398
475
|
end
|
399
476
|
@collection = @collection.page(current_page).per(current_page_size)
|
400
|
-
@records_filtered = default_scope_for_current_model.any? if @collection.empty?
|
477
|
+
@records_filtered = default_scope_for_current_model(archived:).any? if @collection.empty?
|
478
|
+
render :index
|
401
479
|
end
|
402
480
|
|
403
481
|
def buscar_instancia
|
@@ -450,19 +528,11 @@ module PgEngine
|
|
450
528
|
clase_modelo.name.underscore
|
451
529
|
end
|
452
530
|
|
453
|
-
def filtros_y_policy(campos, dflt_sort = nil)
|
531
|
+
def filtros_y_policy(campos, dflt_sort = nil, archived: false)
|
454
532
|
@filtros = PgEngine::FiltrosBuilder.new(
|
455
533
|
self, clase_modelo, campos
|
456
534
|
)
|
457
|
-
scope =
|
458
|
-
|
459
|
-
if nested_id.present?
|
460
|
-
scope = scope.where(nested_key => nested_id)
|
461
|
-
scope = scope.undiscarded if scope.respond_to?(:undiscarded)
|
462
|
-
elsif scope.respond_to?(:kept)
|
463
|
-
scope = scope.kept
|
464
|
-
end
|
465
|
-
# Soft deleted
|
535
|
+
scope = default_scope_for_current_model(archived:)
|
466
536
|
|
467
537
|
shared_context = Ransack::Adapters::ActiveRecord::Context.new(scope)
|
468
538
|
@q = clase_modelo.ransack(params[:q], context: shared_context)
|
@@ -471,20 +541,30 @@ module PgEngine
|
|
471
541
|
shared_context.evaluate(@q)
|
472
542
|
end
|
473
543
|
|
474
|
-
def
|
544
|
+
def soft_delete_filter(scope, archived:)
|
545
|
+
return scope unless scope.respond_to?(:discarded)
|
546
|
+
|
547
|
+
if nested_id.present?
|
548
|
+
if archived
|
549
|
+
scope.discarded
|
550
|
+
else
|
551
|
+
scope.undiscarded
|
552
|
+
end
|
553
|
+
elsif archived
|
554
|
+
scope.unkept
|
555
|
+
else
|
556
|
+
scope.kept
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
def default_scope_for_current_model(archived: false)
|
475
561
|
scope = policy_scope(clase_modelo)
|
476
562
|
|
477
563
|
if nested_id.present?
|
478
564
|
scope = scope.where(nested_key => nested_id)
|
479
|
-
|
480
|
-
# Skip nested discarded check
|
481
|
-
scope = scope.undiscarded if scope.respond_to?(:undiscarded)
|
482
|
-
elsif scope.respond_to?(:kept)
|
483
|
-
scope = scope.kept
|
484
565
|
end
|
485
|
-
# Soft deleted, including nested discarded check
|
486
566
|
|
487
|
-
scope
|
567
|
+
soft_delete_filter(scope, archived:)
|
488
568
|
end
|
489
569
|
end
|
490
570
|
end
|
@@ -10,10 +10,6 @@ module Users
|
|
10
10
|
add_breadcrumb 'Cuentas'
|
11
11
|
self.skip_default_breadcrumb = true
|
12
12
|
|
13
|
-
before_action(only: :index) { authorize Account }
|
14
|
-
|
15
|
-
before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
|
16
|
-
|
17
13
|
# private
|
18
14
|
|
19
15
|
# def atributos_permitidos
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rubocop:disable Metrics/ClassLength
|
3
4
|
module PgEngine
|
4
5
|
class BaseRecordDecorator < Draper::Decorator
|
5
6
|
include ActionView::Helpers
|
@@ -28,8 +29,7 @@ module PgEngine
|
|
28
29
|
|
29
30
|
def text_for_new
|
30
31
|
klass = object.class
|
31
|
-
|
32
|
-
verb = klass.new.gender == 'f' ? 'Nueva' : 'Nuevo'
|
32
|
+
verb = klass.gender == 'f' ? 'Nueva' : 'Nuevo'
|
33
33
|
"#{verb} #{klass.model_name.human.downcase}"
|
34
34
|
end
|
35
35
|
|
@@ -57,22 +57,50 @@ module PgEngine
|
|
57
57
|
if helpers.using_modal?
|
58
58
|
destroy_link
|
59
59
|
else
|
60
|
-
destroy_link(
|
60
|
+
destroy_link(land_on: :index)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
def destroy_link(confirm_text: '¿Confirmás que querés borrar el registro?', klass: 'btn-light',
|
64
|
+
def destroy_link(confirm_text: '¿Confirmás que querés borrar el registro?', klass: 'btn-light', land_on: nil)
|
65
65
|
return unless Pundit.policy!(Current.user, object).destroy?
|
66
66
|
|
67
|
-
helpers.content_tag :span, rel: :tooltip, title: 'Eliminar' do
|
68
|
-
helpers.link_to object_url + (
|
67
|
+
helpers.content_tag :span, rel: :tooltip, title: 'Eliminar definitivamente' do
|
68
|
+
helpers.link_to object_url + (land_on.present? ? "?land_on=#{land_on}" : ''),
|
69
69
|
data: { 'turbo-confirm': confirm_text, 'turbo-method': :delete },
|
70
|
-
class: "btn btn-sm #{klass}" do
|
70
|
+
class: "btn btn-sm #{klass} text-danger" do
|
71
71
|
helpers.content_tag :span, nil, class: clase_icono('trash-fill')
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
def archive_link(klass: 'btn-light')
|
77
|
+
return unless Pundit.policy!(Current.user, object).archive?
|
78
|
+
|
79
|
+
target_archive = [:archive, pg_namespace, nested_record, object]
|
80
|
+
|
81
|
+
helpers.content_tag :span, rel: :tooltip, title: 'Archivar' do
|
82
|
+
helpers.link_to helpers.url_for(target_archive),
|
83
|
+
data: { 'turbo-method': :post, 'turbo-stream': true },
|
84
|
+
class: "btn btn-sm #{klass}" do
|
85
|
+
helpers.content_tag :span, nil, class: clase_icono('archive-fill')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def restore_link(klass: 'btn-light')
|
91
|
+
return unless Pundit.policy!(Current.user, object).restore?
|
92
|
+
|
93
|
+
target_archive = [:restore, pg_namespace, nested_record, object]
|
94
|
+
|
95
|
+
helpers.content_tag :span, rel: :tooltip, title: 'Desarchivar' do
|
96
|
+
helpers.link_to helpers.url_for(target_archive),
|
97
|
+
data: { 'turbo-method': :post, 'turbo-stream': true },
|
98
|
+
class: "btn btn-sm #{klass}" do
|
99
|
+
helpers.content_tag(:span, nil, class: clase_icono('arrow-counterclockwise')) + ' Desarchivar'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
76
104
|
def edit_link(text: ' Modificar', klass: 'btn-warning')
|
77
105
|
return unless Pundit.policy!(Current.user, object).edit?
|
78
106
|
|
@@ -103,14 +131,11 @@ module PgEngine
|
|
103
131
|
end
|
104
132
|
end
|
105
133
|
|
106
|
-
def export_link(url, text: ''
|
134
|
+
def export_link(url, text: '')
|
107
135
|
return unless Pundit.policy!(Current.user, object).export?
|
108
136
|
|
109
|
-
helpers.content_tag :
|
110
|
-
helpers.content_tag
|
111
|
-
class: "btn btn-sm #{klass}", href: url_change_format(url, 'xlsx') do
|
112
|
-
"#{helpers.content_tag(:span, nil, class: clase_icono('file-earmark-excel-fill'))} #{text}".html_safe
|
113
|
-
end
|
137
|
+
helpers.content_tag :a, target: '_blank', class: 'icon-link dropdown-item lh-1', href: url_change_format(url, 'xlsx') do
|
138
|
+
"#{helpers.content_tag(:span, nil, class: clase_icono('file-earmark-excel-fill'))} #{text}".html_safe
|
114
139
|
end
|
115
140
|
end
|
116
141
|
|
@@ -182,3 +207,4 @@ module PgEngine
|
|
182
207
|
end
|
183
208
|
end
|
184
209
|
end
|
210
|
+
# rubocop:enable Metrics/ClassLength
|
@@ -18,13 +18,13 @@ module PgEngine
|
|
18
18
|
sort_field = sort_field.to_s.sub(/_text\z/, '')
|
19
19
|
end
|
20
20
|
|
21
|
+
# Unsuffixed
|
21
22
|
campo = campo.to_s.sub(/_f\z/, '')
|
22
23
|
campo = campo.to_s.sub(/_text\z/, '')
|
23
24
|
|
24
25
|
clase = options[:clase] || @clase_modelo
|
25
|
-
|
26
|
-
|
27
|
-
human_name = clase.human_attribute_name(key, default: dflt)
|
26
|
+
|
27
|
+
human_name = scoped_human_attr_name(clase, campo, 'listado_header')
|
28
28
|
|
29
29
|
if options[:ordenable]
|
30
30
|
if sort_field.is_a? Array
|
@@ -37,6 +37,20 @@ module PgEngine
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
+
def scoped_human_attr_name(clase, campo, scope)
|
41
|
+
action_key = build_scoped_key(clase, campo, scope, action_name)
|
42
|
+
scope_key = build_scoped_key(clase, campo, scope)
|
43
|
+
|
44
|
+
I18n.t(action_key, default: [scope_key, clase.human_attribute_name(campo)])
|
45
|
+
end
|
46
|
+
|
47
|
+
def build_scoped_key(clase, campo, scope = nil, subscope = nil)
|
48
|
+
campo = "#{campo}/scoped" if scope.present?
|
49
|
+
scope = "#{subscope}/#{scope}" if subscope.present?
|
50
|
+
|
51
|
+
['activerecord.attributes', clase.model_name.i18n_key, campo, scope].compact.join('.').to_sym
|
52
|
+
end
|
53
|
+
|
40
54
|
def default_order(campo)
|
41
55
|
columna = @clase_modelo.columns.find { _1.name == campo.to_s }
|
42
56
|
if columna && columna.type.to_s.include?('date')
|