pg_rails 7.2.3 → 7.3.1
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/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}"
|