pg_rails 7.2.3 → 7.3.1
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.
- checksums.yaml +4 -4
- data/pg_associable/app/helpers/pg_associable/form_builder_methods.rb +9 -2
- data/pg_associable/app/helpers/pg_associable/helpers.rb +4 -5
- data/pg_associable/app/javascript/modal_controller.js +80 -6
- data/pg_associable/spec/system/associable_spec.rb +30 -7
- data/pg_engine/app/assets/stylesheets/pg_rails_b5.scss +5 -0
- data/pg_engine/app/components/actions_component.rb +14 -0
- data/pg_engine/app/components/asociable_modal_component.html.slim +6 -0
- data/pg_engine/app/components/asociable_modal_component.rb +7 -0
- data/pg_engine/app/components/date_selector_component.rb +2 -2
- data/pg_engine/app/components/modal_component.html.slim +5 -0
- data/pg_engine/app/components/modal_component.rb +11 -0
- data/pg_engine/app/components/modal_content_component.rb +29 -0
- data/pg_engine/app/components/search_bar_component.html.slim +1 -1
- data/pg_engine/app/controllers/admin/accounts_controller.rb +1 -1
- data/pg_engine/app/controllers/admin/email_logs_controller.rb +1 -1
- data/pg_engine/app/controllers/admin/emails_controller.rb +4 -21
- data/pg_engine/app/controllers/admin/user_accounts_controller.rb +1 -1
- data/pg_engine/app/controllers/admin/users_controller.rb +1 -1
- data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +288 -133
- data/pg_engine/app/controllers/pg_engine/base_controller.rb +5 -0
- data/pg_engine/app/controllers/public/mensaje_contactos_controller.rb +1 -1
- data/pg_engine/app/decorators/pg_engine/base_record_decorator.rb +36 -10
- data/pg_engine/app/helpers/pg_engine/flash_helper.rb +6 -2
- data/pg_engine/app/helpers/pg_engine/form_helper.rb +15 -2
- data/pg_engine/app/helpers/pg_engine/frame_helper.rb +52 -0
- data/pg_engine/app/lib/pg_engine/bootstrap5_breadcrumbs_builder.rb +22 -0
- data/pg_engine/app/lib/pg_engine/filtros_builder.rb +3 -2
- data/pg_engine/app/models/current.rb +1 -1
- data/pg_engine/app/models/email.rb +2 -0
- data/pg_engine/app/models/pg_engine/base_record.rb +13 -0
- data/pg_engine/app/views/admin/accounts/_form.html.slim +1 -4
- data/pg_engine/app/views/admin/email_logs/_form.html.slim +2 -5
- data/pg_engine/app/views/admin/emails/_form.html.slim +13 -13
- data/pg_engine/app/views/admin/emails/_send.html.slim +0 -1
- data/pg_engine/app/views/admin/emails/show.html.slim +19 -20
- data/pg_engine/app/views/admin/eventos/new.html.slim +0 -2
- data/pg_engine/app/views/admin/user_accounts/_form.html.slim +1 -4
- data/pg_engine/app/views/admin/users/_form.html.slim +1 -4
- data/pg_engine/app/views/pg_engine/base/edit.html.slim +1 -2
- data/pg_engine/app/views/pg_engine/base/index.html.slim +6 -3
- data/pg_engine/app/views/pg_engine/base/new.html.slim +1 -2
- data/pg_engine/app/views/public/mensaje_contactos/new.html.slim +2 -5
- data/pg_engine/config/initializers/kaminari.rb +3 -0
- data/pg_engine/config/initializers/ransack_memory.rb +13 -2
- data/pg_engine/config/locales/es.yml +1 -1
- data/pg_engine/lib/pg_engine/utils/pg_logger.rb +10 -10
- data/pg_engine/spec/controllers/admin/accounts_controller_spec.rb +2 -2
- data/pg_engine/spec/controllers/admin/email_logs_controller_spec.rb +2 -2
- data/pg_engine/spec/controllers/admin/emails_controller_spec.rb +2 -2
- data/pg_engine/spec/controllers/admin/user_accounts_controller_spec.rb +2 -2
- data/pg_engine/spec/controllers/admin/users_controller_spec.rb +2 -2
- data/pg_engine/spec/controllers/concerns/pg_engine/resource_helper_spec.rb +0 -2
- data/pg_engine/spec/lib/pg_engine/form_helper_spec.rb +51 -0
- data/pg_engine/spec/system/breadcrumbs_spec.rb +61 -0
- data/pg_engine/spec/system/destroy_spec.rb +1 -1
- data/pg_engine/spec/system/login_spec.rb +1 -1
- data/pg_engine/spec/system/modal_windows_spec.rb +89 -0
- data/pg_engine/spec/system/send_mail_spec.rb +1 -1
- data/pg_layout/app/javascript/application.js +38 -0
- data/pg_layout/app/javascript/config/turbo_rails/index.js +4 -1
- data/pg_layout/app/javascript/controllers/embedded_frame_controller.js +10 -0
- data/pg_layout/app/javascript/controllers/index.js +2 -0
- data/pg_layout/app/javascript/controllers/popover_toggler_controller.js +3 -2
- data/pg_layout/app/javascript/controllers/tooltip_controller.js +8 -0
- data/pg_layout/app/javascript/elements/index.js +1 -0
- data/pg_layout/app/javascript/elements/pg_event.js +13 -0
- data/pg_layout/app/views/devise/confirmations/new.html.erb +0 -1
- data/pg_layout/app/views/devise/passwords/edit.html.erb +0 -2
- data/pg_layout/app/views/devise/passwords/new.html.erb +0 -2
- data/pg_layout/app/views/devise/registrations/edit.html.erb +0 -2
- data/pg_layout/app/views/devise/registrations/new.html.erb +0 -2
- data/pg_layout/app/views/devise/unlocks/new.html.erb +0 -1
- data/pg_layout/app/views/layouts/pg_layout/base.html.slim +45 -17
- data/pg_layout/app/views/layouts/pg_layout/containerized.html.slim +1 -1
- data/pg_rails/lib/version.rb +1 -1
- data/pg_rails/scss/bootstrap_overrides.scss +2 -1
- data/pg_rails/scss/pg_rails.scss +8 -1
- data/pg_scaffold/lib/generators/pg_rspec/scaffold/templates/controller_spec.rb +2 -2
- data/pg_scaffold/lib/generators/pg_scaffold/templates/controller.rb +2 -4
- data/pg_scaffold/lib/generators/pg_slim/templates/_form.html.slim +2 -5
- data/pg_scaffold/lib/generators/pg_slim/templates/show.html.slim +1 -1
- metadata +17 -4
- data/pg_associable/app/views/pg_engine/base/_pg_associable_modal.html.slim +0 -14
- data/pg_layout/app/views/pg_layout/_modal_show.html.slim +0 -14
|
@@ -1,12 +1,115 @@
|
|
|
1
1
|
module PgEngine
|
|
2
2
|
module Resource
|
|
3
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
3
4
|
def self.included(clazz)
|
|
4
|
-
|
|
5
|
+
class << clazz
|
|
6
|
+
# This is a per class variable, all subclasses of clazz inherit it
|
|
7
|
+
# BUT **the values are independent between all of them**
|
|
8
|
+
attr_accessor :nested_class, :nested_key, :clase_modelo
|
|
9
|
+
|
|
10
|
+
# TODO: separar los endpoints de la lógica de filtros para evitar esta variable
|
|
11
|
+
# en Agenda
|
|
12
|
+
attr_accessor :skip_default_breadcrumb
|
|
13
|
+
end
|
|
14
|
+
clazz.delegate :nested_key, :nested_class, :clase_modelo, to: clazz
|
|
15
|
+
|
|
16
|
+
clazz.helper_method :nested_class, :nested_key, :clase_modelo
|
|
17
|
+
clazz.helper_method :nested_record, :nested_id
|
|
18
|
+
|
|
5
19
|
clazz.helper_method :atributos_para_listar
|
|
6
20
|
clazz.helper_method :atributos_para_mostrar
|
|
7
21
|
clazz.helper_method :current_page_size
|
|
8
22
|
clazz.helper_method :show_filters?
|
|
9
23
|
clazz.helper_method :available_page_sizes
|
|
24
|
+
|
|
25
|
+
clazz.before_action do
|
|
26
|
+
# TODO: quitar esto, que se use el attr_accessor
|
|
27
|
+
# o sea, quitar todas las referencias a @clase_modelo
|
|
28
|
+
@clase_modelo = clase_modelo
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
clazz.before_action unless: -> { clazz.skip_default_breadcrumb } do
|
|
32
|
+
if nested_record.present?
|
|
33
|
+
# Link al nested, siempre que sea no sea un embedded frame
|
|
34
|
+
# ya que en tal caso se supone que el nested está visible
|
|
35
|
+
# en el main frame. Además, si es un modal abierto desde
|
|
36
|
+
# el nested record, no muestro el link al mismo.
|
|
37
|
+
unless frame_embedded?
|
|
38
|
+
if modal_targeted? && referred_by?(nested_record)
|
|
39
|
+
add_breadcrumb nested_record.decorate.to_s_short
|
|
40
|
+
else
|
|
41
|
+
add_breadcrumb nested_record.decorate.to_s_short,
|
|
42
|
+
nested_record.decorate.target_object
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Texto de index pero sin link, porque se supone que es un
|
|
47
|
+
# embedded index o viene de tal
|
|
48
|
+
add_breadcrumb clase_modelo.nombre_plural
|
|
49
|
+
|
|
50
|
+
elsif !modal_targeted?
|
|
51
|
+
# Link al index, siempre que no sea un modal, porque en tal
|
|
52
|
+
# caso se supone que el index está visible en el main frame
|
|
53
|
+
if clase_modelo.present?
|
|
54
|
+
add_breadcrumb clase_modelo.nombre_plural,
|
|
55
|
+
url_for([pg_namespace, nested_record, clase_modelo])
|
|
56
|
+
else
|
|
57
|
+
# :nocov:
|
|
58
|
+
pg_warn 'clase_modelo is nil'
|
|
59
|
+
# :nocov:
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
clazz.layout :set_layout
|
|
65
|
+
end
|
|
66
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
67
|
+
|
|
68
|
+
def referred_by?(object)
|
|
69
|
+
url_for(object.decorate.target_object) == request.referer
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def nested_id
|
|
73
|
+
return unless nested_key.present? && nested_class.present?
|
|
74
|
+
|
|
75
|
+
id = params[nested_key]
|
|
76
|
+
|
|
77
|
+
# if using hashid-rails
|
|
78
|
+
if nested_class.respond_to? :decode_id
|
|
79
|
+
id = nested_class.decode_id(id)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
id
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def nested_record
|
|
86
|
+
return if nested_id.blank?
|
|
87
|
+
|
|
88
|
+
nested_class.find(nested_id)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def accepts_turbo_stream?
|
|
92
|
+
request.headers['Accept'].present? &&
|
|
93
|
+
request.headers['Accept'].include?('text/vnd.turbo-stream.html')
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def respond_with_modal?
|
|
97
|
+
can_open_modal? || modal_targeted?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def can_open_modal?
|
|
101
|
+
request.get? &&
|
|
102
|
+
clase_modelo.default_modal &&
|
|
103
|
+
accepts_turbo_stream? &&
|
|
104
|
+
!in_modal?
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def set_layout
|
|
108
|
+
if action_name == 'index'
|
|
109
|
+
'pg_layout/base'
|
|
110
|
+
else
|
|
111
|
+
'pg_layout/containerized'
|
|
112
|
+
end
|
|
10
113
|
end
|
|
11
114
|
|
|
12
115
|
# Public endpoints
|
|
@@ -25,18 +128,45 @@ module PgEngine
|
|
|
25
128
|
end
|
|
26
129
|
|
|
27
130
|
def show
|
|
28
|
-
add_breadcrumb instancia_modelo.to_s_short, instancia_modelo.target_object
|
|
29
|
-
|
|
30
131
|
pg_respond_show
|
|
31
132
|
end
|
|
32
133
|
|
|
134
|
+
# FIXME: refactor
|
|
135
|
+
def respond_with_modal(component)
|
|
136
|
+
content = component.render_in(view_context)
|
|
137
|
+
|
|
138
|
+
if can_open_modal?
|
|
139
|
+
modal = ModalComponent.new.with_content(content)
|
|
140
|
+
render turbo_stream: turbo_stream.append_all('body', modal)
|
|
141
|
+
else
|
|
142
|
+
render html: content
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
33
146
|
def new
|
|
34
|
-
|
|
147
|
+
if can_open_modal?
|
|
148
|
+
path = [request.path, request.query_string].compact.join('?')
|
|
149
|
+
component = ModalContentComponent.new(src: path)
|
|
150
|
+
respond_with_modal(component)
|
|
151
|
+
else
|
|
152
|
+
add_breadcrumb instancia_modelo.submit_default_value
|
|
153
|
+
end
|
|
35
154
|
end
|
|
36
155
|
|
|
37
156
|
def edit
|
|
38
|
-
|
|
39
|
-
|
|
157
|
+
if can_open_modal?
|
|
158
|
+
path = [request.path, request.query_string].compact.join('?')
|
|
159
|
+
component = ModalContentComponent.new(src: path)
|
|
160
|
+
respond_with_modal(component)
|
|
161
|
+
else
|
|
162
|
+
if modal_targeted? && referred_by?(instancia_modelo)
|
|
163
|
+
add_breadcrumb instancia_modelo.to_s_short
|
|
164
|
+
else
|
|
165
|
+
add_breadcrumb instancia_modelo.to_s_short,
|
|
166
|
+
instancia_modelo.target_object
|
|
167
|
+
end
|
|
168
|
+
add_breadcrumb 'Modificando'
|
|
169
|
+
end
|
|
40
170
|
end
|
|
41
171
|
|
|
42
172
|
def create
|
|
@@ -55,36 +185,59 @@ module PgEngine
|
|
|
55
185
|
protected
|
|
56
186
|
|
|
57
187
|
def default_sort
|
|
58
|
-
|
|
188
|
+
'id desc'
|
|
59
189
|
end
|
|
60
190
|
|
|
61
191
|
def available_page_sizes
|
|
62
|
-
[10, 20, 30, 50, 100].push(current_page_size).uniq.sort
|
|
192
|
+
[5, 10, 20, 30, 50, 100].push(current_page_size).uniq.sort
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def show_filters_by_default?
|
|
196
|
+
true
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def filters_applied?
|
|
200
|
+
params[RansackMemory::Core.config[:param].presence || :q].present?
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def session_key_identifier
|
|
204
|
+
::RansackMemory::Core.config[:session_key_format]
|
|
205
|
+
.gsub('%controller_name%', controller_path.parameterize.underscore)
|
|
206
|
+
.gsub('%action_name%', action_name)
|
|
207
|
+
.gsub('%request_format%', request.format.symbol.to_s)
|
|
208
|
+
.gsub('%turbo_frame%', request.headers['Turbo-Frame'] || 'top')
|
|
209
|
+
# FIXME: rename to main?
|
|
63
210
|
end
|
|
64
211
|
|
|
65
212
|
def show_filters?
|
|
66
|
-
|
|
67
|
-
|
|
213
|
+
return true if filters_applied?
|
|
214
|
+
|
|
215
|
+
idtf = "show-filters_#{session_key_identifier}"
|
|
68
216
|
|
|
69
217
|
if params[:ocultar_filtros]
|
|
70
|
-
session[idtf] =
|
|
218
|
+
session[idtf] = false
|
|
71
219
|
elsif params[:mostrar_filtros]
|
|
72
220
|
session[idtf] = true
|
|
73
221
|
end
|
|
74
222
|
|
|
75
|
-
session[idtf]
|
|
223
|
+
if session[idtf].nil?
|
|
224
|
+
show_filters_by_default?
|
|
225
|
+
else
|
|
226
|
+
session[idtf]
|
|
227
|
+
end
|
|
76
228
|
end
|
|
77
229
|
|
|
78
230
|
def current_page_size
|
|
79
|
-
|
|
80
|
-
|
|
231
|
+
aux = params[:page_size].presence&.to_i
|
|
232
|
+
if aux.present? && aux.positive?
|
|
233
|
+
session[page_size_session_key] = aux
|
|
81
234
|
end
|
|
82
235
|
|
|
83
236
|
session[page_size_session_key].presence || default_page_size
|
|
84
237
|
end
|
|
85
238
|
|
|
86
239
|
def page_size_session_key
|
|
87
|
-
"#{
|
|
240
|
+
"page_size_#{session_key_identifier}"
|
|
88
241
|
end
|
|
89
242
|
|
|
90
243
|
def default_page_size
|
|
@@ -93,57 +246,52 @@ module PgEngine
|
|
|
93
246
|
|
|
94
247
|
def pg_respond_update
|
|
95
248
|
object = instancia_modelo
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
format.html
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
249
|
+
if (@saved = object.save)
|
|
250
|
+
respond_to do |format|
|
|
251
|
+
format.html do
|
|
252
|
+
if in_modal?
|
|
253
|
+
body = <<~HTML.html_safe
|
|
254
|
+
<pg-event data-event-name="pg:record-updated" data-turbo-temporary
|
|
255
|
+
data-response='#{object.decorate.to_json}'></pg-event>
|
|
256
|
+
HTML
|
|
257
|
+
render html: ModalContentComponent.new.with_content(body)
|
|
258
|
+
.render_in(view_context)
|
|
259
|
+
else
|
|
260
|
+
redirect_to object.decorate.target_object
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
format.json do
|
|
264
|
+
render json: object.decorate.as_json
|
|
265
|
+
end
|
|
105
266
|
end
|
|
267
|
+
else
|
|
268
|
+
add_breadcrumb instancia_modelo.decorate.to_s_short, instancia_modelo.decorate.target_object
|
|
269
|
+
add_breadcrumb 'Modificando'
|
|
270
|
+
# TODO: esto solucionaría el problema?
|
|
271
|
+
# self.instancia_modelo = instancia_modelo.decorate
|
|
272
|
+
#
|
|
273
|
+
render :edit, status: :unprocessable_entity
|
|
106
274
|
end
|
|
107
275
|
end
|
|
108
276
|
|
|
109
277
|
def pg_respond_create
|
|
110
278
|
object = instancia_modelo
|
|
111
|
-
|
|
112
|
-
if
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
<div data-modal-target="response" data-response='#{object.decorate.to_json}'></div>
|
|
119
|
-
HTML
|
|
120
|
-
)
|
|
121
|
-
# FIXME: handlear json
|
|
122
|
-
# render json: object.decorate, content_type: 'application/json'
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
format.html do
|
|
126
|
-
if params[:save_and_next] == 'true'
|
|
127
|
-
new_path = "#{url_for(@clase_modelo)}/new"
|
|
128
|
-
redirect_to new_path, notice: "#{@clase_modelo.nombre_singular} creado."
|
|
129
|
-
else
|
|
130
|
-
redirect_to object.decorate.target_object
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
format.json { render json: object.decorate }
|
|
279
|
+
if (@saved = object.save)
|
|
280
|
+
if in_modal?
|
|
281
|
+
body = <<~HTML.html_safe
|
|
282
|
+
<pg-event data-event-name="pg:record-created" data-turbo-temporary
|
|
283
|
+
data-response='#{object.decorate.to_json}'></pg-event>
|
|
284
|
+
HTML
|
|
285
|
+
render turbo_stream: turbo_stream.append(current_turbo_frame, body)
|
|
134
286
|
else
|
|
135
|
-
|
|
136
|
-
# self.instancia_modelo = instancia_modelo.decorate
|
|
137
|
-
if params[:asociable]
|
|
138
|
-
format.turbo_stream do
|
|
139
|
-
# FIXME: agregar , status: :unprocessable_entity
|
|
140
|
-
render turbo_stream:
|
|
141
|
-
turbo_stream.update_all('.modal.show .pg-associable-form', partial: 'form', locals: { asociable: true })
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
format.html { render :new, status: :unprocessable_entity }
|
|
145
|
-
format.json { render json: object.errors.full_messages, status: :unprocessable_entity }
|
|
287
|
+
redirect_to object.decorate.target_object
|
|
146
288
|
end
|
|
289
|
+
else
|
|
290
|
+
add_breadcrumb instancia_modelo.decorate.submit_default_value
|
|
291
|
+
# TODO: esto solucionaría el problema?
|
|
292
|
+
# self.instancia_modelo = instancia_modelo.decorate
|
|
293
|
+
|
|
294
|
+
render :new, status: :unprocessable_entity
|
|
147
295
|
end
|
|
148
296
|
end
|
|
149
297
|
|
|
@@ -153,104 +301,98 @@ module PgEngine
|
|
|
153
301
|
format.html { render_listing }
|
|
154
302
|
format.xlsx do
|
|
155
303
|
render xlsx: 'download',
|
|
156
|
-
filename: "#{
|
|
304
|
+
filename: "#{clase_modelo.nombre_plural.gsub(' ', '-').downcase}" \
|
|
157
305
|
"-#{Time.zone.now.strftime('%Y-%m-%d-%H.%M.%S')}.xlsx"
|
|
158
306
|
end
|
|
159
307
|
end
|
|
160
308
|
end
|
|
161
309
|
|
|
162
|
-
def pg_respond_show
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
format.turbo_stream do
|
|
168
|
-
render turbo_stream: turbo_stream.append_all(
|
|
169
|
-
'body', partial: 'pg_layout/modal_show', locals: { object: }
|
|
170
|
-
)
|
|
171
|
-
end
|
|
172
|
-
end
|
|
310
|
+
def pg_respond_show
|
|
311
|
+
if can_open_modal?
|
|
312
|
+
path = [request.path, request.query_string].compact.join('?')
|
|
313
|
+
component = ModalContentComponent.new(src: path)
|
|
314
|
+
respond_with_modal(component)
|
|
173
315
|
else
|
|
174
|
-
|
|
175
|
-
format.json { render json: object }
|
|
176
|
-
format.html
|
|
177
|
-
end
|
|
316
|
+
add_breadcrumb instancia_modelo.to_s_short, instancia_modelo.target_object
|
|
178
317
|
end
|
|
179
318
|
end
|
|
180
319
|
|
|
320
|
+
def destroyed_message(model)
|
|
321
|
+
"#{model.model_name.human} #{model.gender == 'f' ? 'borrada' : 'borrado'}"
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
181
325
|
def pg_respond_destroy(model, redirect_url = nil)
|
|
182
326
|
if destroy_model(model)
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
327
|
+
# FIXME: rename to main
|
|
328
|
+
if turbo_frame? && current_turbo_frame != 'top'
|
|
329
|
+
body = <<~HTML.html_safe
|
|
330
|
+
<pg-event data-event-name="pg:record-destroyed" data-turbo-temporary>
|
|
331
|
+
</pg-event>
|
|
332
|
+
HTML
|
|
333
|
+
render turbo_stream: turbo_stream.append(current_turbo_frame, body)
|
|
334
|
+
elsif redirect_url.present?
|
|
335
|
+
redirect_to redirect_url, notice: destroyed_message(model), status: :see_other
|
|
336
|
+
elsif accepts_turbo_stream?
|
|
337
|
+
body = <<~HTML.html_safe
|
|
338
|
+
<pg-event data-event-name="pg:record-destroyed" data-turbo-temporary>
|
|
339
|
+
</pg-event>
|
|
340
|
+
HTML
|
|
341
|
+
render turbo_stream: turbo_stream.append_all('body', body)
|
|
342
|
+
else
|
|
343
|
+
redirect_back(fallback_location: root_path,
|
|
344
|
+
notice: destroyed_message(model), status: 303)
|
|
200
345
|
end
|
|
346
|
+
elsif in_modal?
|
|
347
|
+
|
|
348
|
+
flash.now[:alert] = @error_message
|
|
349
|
+
render turbo_stream: render_turbo_stream_flash_messages(to: '.modal-body .flash')
|
|
350
|
+
elsif accepts_turbo_stream?
|
|
351
|
+
flash.now[:alert] = @error_message
|
|
352
|
+
render turbo_stream: render_turbo_stream_flash_messages
|
|
201
353
|
else
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if model.respond_to?(:associated_elements) && model.associated_elements.present?
|
|
205
|
-
@model = model
|
|
206
|
-
render destroy_error_details_view
|
|
207
|
-
else
|
|
208
|
-
flash[:alert] = @error_message
|
|
209
|
-
redirect_back(fallback_location: root_path, status: 303)
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
format.json { render json: { error: @error_message }, status: :unprocessable_entity }
|
|
213
|
-
end
|
|
354
|
+
flash[:alert] = @error_message
|
|
355
|
+
redirect_back(fallback_location: root_path, status: 303)
|
|
214
356
|
end
|
|
215
357
|
end
|
|
216
|
-
|
|
217
|
-
# TODO: crear esta vista en pg_rails
|
|
218
|
-
def destroy_error_details_view
|
|
219
|
-
'destroy_error_details'
|
|
220
|
-
end
|
|
358
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
221
359
|
|
|
222
360
|
def destroy_model(model)
|
|
223
361
|
@error_message = 'No se pudo eliminar el registro'
|
|
362
|
+
|
|
224
363
|
begin
|
|
225
364
|
destroy_method = model.respond_to?(:discard) ? :discard : :destroy
|
|
226
365
|
return true if model.send(destroy_method)
|
|
227
366
|
|
|
228
|
-
@error_message = model.errors.full_messages.join(', ')
|
|
367
|
+
@error_message = model.errors.full_messages.join(', ').presence || @error_message
|
|
368
|
+
|
|
229
369
|
false
|
|
230
370
|
rescue ActiveRecord::InvalidForeignKey => e
|
|
231
|
-
# class_name = /from table \"(?<table_name>[\p{L}_]*)\"/.match(e.message)[:table_name].singularize.camelcase
|
|
232
|
-
# # pk_id = /from table \"(?<pk_id>[\p{L}_]*)\"/.match(e.message)[:pk_id].singularize.camelcase
|
|
233
|
-
# clazz = Object.const_get class_name
|
|
234
|
-
# objects = clazz.where(model.class.table_name.singularize => model)
|
|
235
371
|
model_name = t("activerecord.models.#{model.class.name.underscore}")
|
|
236
372
|
@error_message = "#{model_name} no se pudo borrar porque tiene elementos asociados."
|
|
237
|
-
|
|
373
|
+
pg_warn(e)
|
|
238
374
|
end
|
|
375
|
+
|
|
239
376
|
false
|
|
240
377
|
end
|
|
241
378
|
|
|
242
379
|
def render_listing
|
|
243
|
-
|
|
380
|
+
total = @collection.count
|
|
381
|
+
current_page = params[:page].presence&.to_i || 1
|
|
382
|
+
if current_page_size * (current_page - 1) > total
|
|
383
|
+
current_page = (total.to_f / current_page_size).ceil
|
|
384
|
+
end
|
|
385
|
+
@collection = @collection.page(current_page).per(current_page_size)
|
|
244
386
|
@records_filtered = default_scope_for_current_model.any? if @collection.empty?
|
|
245
387
|
end
|
|
246
388
|
|
|
247
389
|
def buscar_instancia
|
|
248
|
-
if Object.const_defined?('FriendlyId') &&
|
|
249
|
-
|
|
250
|
-
elsif
|
|
251
|
-
|
|
390
|
+
if Object.const_defined?('FriendlyId') && clase_modelo.is_a?(FriendlyId)
|
|
391
|
+
clase_modelo.friendly.find(params[:id])
|
|
392
|
+
elsif clase_modelo.respond_to? :find_by_hashid!
|
|
393
|
+
clase_modelo.find_by_hashid!(params[:id])
|
|
252
394
|
else
|
|
253
|
-
|
|
395
|
+
clase_modelo.find(params[:id])
|
|
254
396
|
end
|
|
255
397
|
rescue ActiveRecord::RecordNotFound
|
|
256
398
|
raise PgEngine::PageNotFoundError
|
|
@@ -258,7 +400,10 @@ module PgEngine
|
|
|
258
400
|
|
|
259
401
|
def set_instancia_modelo
|
|
260
402
|
if action_name.in? %w[new create]
|
|
261
|
-
self.instancia_modelo =
|
|
403
|
+
self.instancia_modelo = clase_modelo.new(modelo_params)
|
|
404
|
+
if nested_id.present?
|
|
405
|
+
instancia_modelo.send("#{nested_key}=", nested_id)
|
|
406
|
+
end
|
|
262
407
|
else
|
|
263
408
|
self.instancia_modelo = buscar_instancia
|
|
264
409
|
|
|
@@ -291,12 +436,7 @@ module PgEngine
|
|
|
291
436
|
end
|
|
292
437
|
|
|
293
438
|
def nombre_modelo
|
|
294
|
-
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
def clase_modelo
|
|
298
|
-
# agarro la variable o intento con el nombre del controller
|
|
299
|
-
@clase_modelo ||= self.class.name.singularize.gsub('Controller', '').constantize
|
|
439
|
+
clase_modelo.name.underscore
|
|
300
440
|
end
|
|
301
441
|
|
|
302
442
|
def filtros_y_policy(campos, dflt_sort = nil)
|
|
@@ -305,20 +445,35 @@ module PgEngine
|
|
|
305
445
|
)
|
|
306
446
|
scope = policy_scope(clase_modelo)
|
|
307
447
|
|
|
308
|
-
|
|
448
|
+
if nested_id.present?
|
|
449
|
+
scope = scope.where(nested_key => nested_id)
|
|
450
|
+
scope = scope.undiscarded if scope.respond_to?(:undiscarded)
|
|
451
|
+
elsif scope.respond_to?(:kept)
|
|
452
|
+
scope = scope.kept
|
|
453
|
+
end
|
|
454
|
+
# Soft deleted
|
|
309
455
|
|
|
310
456
|
shared_context = Ransack::Adapters::ActiveRecord::Context.new(scope)
|
|
311
|
-
@q =
|
|
312
|
-
|
|
457
|
+
@q = clase_modelo.ransack(params[:q], context: shared_context)
|
|
313
458
|
@q.sorts = dflt_sort if @q.sorts.empty? && dflt_sort.present?
|
|
314
459
|
|
|
315
460
|
shared_context.evaluate(@q)
|
|
316
461
|
end
|
|
317
462
|
|
|
318
463
|
def default_scope_for_current_model
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
464
|
+
scope = policy_scope(clase_modelo)
|
|
465
|
+
|
|
466
|
+
if nested_id.present?
|
|
467
|
+
scope = scope.where(nested_key => nested_id)
|
|
468
|
+
|
|
469
|
+
# Skip nested discarded check
|
|
470
|
+
scope = scope.undiscarded if scope.respond_to?(:undiscarded)
|
|
471
|
+
elsif scope.respond_to?(:kept)
|
|
472
|
+
scope = scope.kept
|
|
473
|
+
end
|
|
474
|
+
# Soft deleted, including nested discarded check
|
|
475
|
+
|
|
476
|
+
scope
|
|
322
477
|
end
|
|
323
478
|
end
|
|
324
479
|
end
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
module PgEngine
|
|
4
4
|
# rubocop:disable Rails/ApplicationController
|
|
5
5
|
class BaseController < ActionController::Base
|
|
6
|
+
before_action do
|
|
7
|
+
Current.controller = self
|
|
8
|
+
end
|
|
9
|
+
|
|
6
10
|
# rubocop:enable Rails/ApplicationController
|
|
7
11
|
include Pundit::Authorization
|
|
8
12
|
include PrintHelper
|
|
@@ -10,6 +14,7 @@ module PgEngine
|
|
|
10
14
|
include FlashHelper
|
|
11
15
|
include RouteHelper
|
|
12
16
|
include PgAssociable::Helpers
|
|
17
|
+
include FrameHelper
|
|
13
18
|
|
|
14
19
|
class Redirect < PgEngine::Error
|
|
15
20
|
attr_accessor :url
|
|
@@ -42,10 +42,14 @@ module PgEngine
|
|
|
42
42
|
# rubocop:enable Style/MissingRespondToMissing
|
|
43
43
|
|
|
44
44
|
def destroy_link_redirect
|
|
45
|
-
|
|
45
|
+
if helpers.using_modal?
|
|
46
|
+
destroy_link
|
|
47
|
+
else
|
|
48
|
+
destroy_link(redirect_to: helpers.url_for(target_index))
|
|
49
|
+
end
|
|
46
50
|
end
|
|
47
51
|
|
|
48
|
-
def destroy_link(confirm_text: '¿
|
|
52
|
+
def destroy_link(confirm_text: '¿Confirmás que querés borrar el registro?', klass: 'btn-light', redirect_to: nil)
|
|
49
53
|
return unless Pundit.policy!(Current.user, object).destroy?
|
|
50
54
|
|
|
51
55
|
helpers.content_tag :span, rel: :tooltip, title: 'Eliminar' do
|
|
@@ -61,7 +65,10 @@ module PgEngine
|
|
|
61
65
|
return unless Pundit.policy!(Current.user, object).edit?
|
|
62
66
|
|
|
63
67
|
helpers.content_tag :span, rel: :tooltip, title: 'Modificar' do
|
|
64
|
-
helpers.link_to edit_object_url,
|
|
68
|
+
helpers.link_to edit_object_url,
|
|
69
|
+
class: "btn btn-sm #{klass}",
|
|
70
|
+
'data-turbo-frame': 'modal_content',
|
|
71
|
+
'data-turbo-stream': true do
|
|
65
72
|
helpers.content_tag(:span, nil, class: clase_icono('pencil')) + text
|
|
66
73
|
end
|
|
67
74
|
end
|
|
@@ -71,7 +78,10 @@ module PgEngine
|
|
|
71
78
|
return unless Pundit.policy!(Current.user, object).show?
|
|
72
79
|
|
|
73
80
|
helpers.content_tag :span, rel: :tooltip, title: 'Ver' do
|
|
74
|
-
helpers.link_to object_url,
|
|
81
|
+
helpers.link_to object_url,
|
|
82
|
+
class: "btn btn-sm #{klass}",
|
|
83
|
+
'data-turbo-frame': 'modal_content',
|
|
84
|
+
'data-turbo-stream': true do
|
|
75
85
|
helpers.content_tag(:span, nil, class: clase_icono('eye-fill')) + text
|
|
76
86
|
end
|
|
77
87
|
end
|
|
@@ -88,12 +98,14 @@ module PgEngine
|
|
|
88
98
|
end
|
|
89
99
|
end
|
|
90
100
|
|
|
91
|
-
def new_link(
|
|
101
|
+
def new_link(klass: 'btn-warning')
|
|
92
102
|
return unless Pundit.policy!(Current.user, object).new?
|
|
93
103
|
|
|
94
104
|
helpers.content_tag :span, rel: :tooltip, title: submit_default_value do
|
|
95
|
-
helpers.link_to(new_object_url,
|
|
96
|
-
|
|
105
|
+
helpers.link_to(new_object_url,
|
|
106
|
+
class: "btn btn-sm #{klass}",
|
|
107
|
+
'data-turbo-frame': 'modal_content',
|
|
108
|
+
'data-turbo-stream': true) do
|
|
97
109
|
helpers.content_tag(:span, nil,
|
|
98
110
|
class: clase_icono('plus').to_s) + "<span class='d-none d-sm-inline'> #{submit_default_value}</span>".html_safe
|
|
99
111
|
end
|
|
@@ -105,15 +117,29 @@ module PgEngine
|
|
|
105
117
|
end
|
|
106
118
|
|
|
107
119
|
def new_object_url
|
|
108
|
-
|
|
120
|
+
helpers.url_for(target_new)
|
|
109
121
|
end
|
|
110
122
|
|
|
111
123
|
def object_url
|
|
112
124
|
helpers.url_for(target_object)
|
|
113
125
|
end
|
|
114
126
|
|
|
127
|
+
def nested_record
|
|
128
|
+
# TODO: esto es raro
|
|
129
|
+
return if !Current.controller.respond_to?(:nested_record) ||
|
|
130
|
+
Current.controller.nested_record.nil? ||
|
|
131
|
+
Current.controller.nested_record.instance_of?(object.class)
|
|
132
|
+
|
|
133
|
+
Current.controller.nested_record
|
|
134
|
+
end
|
|
135
|
+
|
|
115
136
|
def target_object
|
|
116
|
-
|
|
137
|
+
[pg_namespace, nested_record, object].compact
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def target_new
|
|
141
|
+
mod_name_sing = object.class.model_name.singular.to_sym
|
|
142
|
+
[:new, pg_namespace, nested_record, mod_name_sing]
|
|
117
143
|
end
|
|
118
144
|
|
|
119
145
|
def target_index
|
|
@@ -123,7 +149,7 @@ module PgEngine
|
|
|
123
149
|
# actionview-7.1.3.2/lib/action_view/helpers/form_helper.rb
|
|
124
150
|
def submit_default_value
|
|
125
151
|
key = :create
|
|
126
|
-
model = object.model_name.human
|
|
152
|
+
model = object.model_name.human.downcase
|
|
127
153
|
defaults = []
|
|
128
154
|
defaults << :"helpers.submit.#{object.model_name.i18n_key}.#{key}"
|
|
129
155
|
defaults << :"helpers.submit.#{key}"
|