pg_rails 7.2.2 → 7.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/pg_associable/app/helpers/pg_associable/form_builder_methods.rb +1 -2
  3. data/pg_associable/app/helpers/pg_associable/helpers.rb +4 -5
  4. data/pg_associable/app/javascript/modal_controller.js +19 -7
  5. data/pg_associable/spec/system/associable_spec.rb +2 -2
  6. data/pg_engine/app/components/actions_component.rb +14 -0
  7. data/pg_engine/app/components/asociable_modal_component.html.slim +6 -0
  8. data/pg_engine/app/components/asociable_modal_component.rb +7 -0
  9. data/pg_engine/app/components/form_modal_component.html.slim +15 -0
  10. data/pg_engine/app/components/form_modal_component.rb +6 -0
  11. data/pg_engine/app/components/modal_component.html.slim +5 -0
  12. data/pg_engine/app/components/modal_component.rb +11 -0
  13. data/pg_engine/app/components/modal_content_component.rb +28 -0
  14. data/pg_engine/app/components/show_modal_component.html.slim +10 -0
  15. data/pg_engine/app/components/show_modal_component.rb +7 -0
  16. data/pg_engine/app/controllers/admin/emails_controller.rb +3 -20
  17. data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +134 -102
  18. data/pg_engine/app/decorators/pg_engine/base_record_decorator.rb +29 -8
  19. data/pg_engine/app/helpers/pg_engine/flash_helper.rb +6 -2
  20. data/pg_engine/app/helpers/pg_engine/form_helper.rb +20 -2
  21. data/pg_engine/app/models/email.rb +2 -0
  22. data/pg_engine/app/models/pg_engine/base_record.rb +11 -0
  23. data/pg_engine/app/views/admin/accounts/_form.html.slim +1 -4
  24. data/pg_engine/app/views/admin/email_logs/_form.html.slim +2 -5
  25. data/pg_engine/app/views/admin/emails/_form.html.slim +13 -13
  26. data/pg_engine/app/views/admin/emails/_send.html.slim +0 -1
  27. data/pg_engine/app/views/admin/emails/show.html.slim +19 -20
  28. data/pg_engine/app/views/admin/eventos/new.html.slim +0 -2
  29. data/pg_engine/app/views/admin/user_accounts/_form.html.slim +1 -4
  30. data/pg_engine/app/views/admin/users/_form.html.slim +1 -4
  31. data/pg_engine/app/views/pg_engine/base/index.html.slim +4 -0
  32. data/pg_engine/app/views/pg_engine/base/new.html.slim +1 -2
  33. data/pg_engine/app/views/public/mensaje_contactos/new.html.slim +2 -5
  34. data/pg_engine/config/initializers/kaminari.rb +3 -0
  35. data/pg_engine/lib/pg_engine/utils/pg_logger.rb +10 -10
  36. data/pg_engine/spec/controllers/admin/accounts_controller_spec.rb +2 -2
  37. data/pg_engine/spec/controllers/admin/email_logs_controller_spec.rb +2 -2
  38. data/pg_engine/spec/controllers/admin/emails_controller_spec.rb +2 -2
  39. data/pg_engine/spec/controllers/admin/user_accounts_controller_spec.rb +2 -2
  40. data/pg_engine/spec/controllers/admin/users_controller_spec.rb +2 -2
  41. data/pg_engine/spec/lib/pg_engine/form_helper_spec.rb +53 -0
  42. data/pg_engine/spec/system/modal_windows_spec.rb +89 -0
  43. data/pg_engine/spec/system/send_mail_spec.rb +1 -1
  44. data/pg_layout/app/javascript/application.js +24 -0
  45. data/pg_layout/app/javascript/controllers/date_selector_controller.js +5 -4
  46. data/pg_layout/app/javascript/controllers/popover_toggler_controller.js +3 -2
  47. data/pg_layout/app/javascript/elements/index.js +1 -0
  48. data/pg_layout/app/javascript/elements/pg_event.js +12 -0
  49. data/pg_layout/app/views/devise/confirmations/new.html.erb +0 -1
  50. data/pg_layout/app/views/devise/passwords/edit.html.erb +0 -2
  51. data/pg_layout/app/views/devise/passwords/new.html.erb +0 -2
  52. data/pg_layout/app/views/devise/registrations/edit.html.erb +0 -2
  53. data/pg_layout/app/views/devise/registrations/new.html.erb +0 -2
  54. data/pg_layout/app/views/devise/unlocks/new.html.erb +0 -1
  55. data/pg_rails/lib/version.rb +1 -1
  56. data/pg_scaffold/lib/generators/pg_rspec/scaffold/templates/controller_spec.rb +2 -2
  57. data/pg_scaffold/lib/generators/pg_slim/templates/_form.html.slim +2 -5
  58. data/pg_scaffold/lib/generators/pg_slim/templates/show.html.slim +1 -1
  59. metadata +17 -4
  60. data/pg_associable/app/views/pg_engine/base/_pg_associable_modal.html.slim +0 -14
  61. data/pg_layout/app/views/pg_layout/_modal_show.html.slim +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20cb7ade648f78aa73ed631d9732326edc5a251a36141d054084366d9a6b9859
4
- data.tar.gz: 38c923c5650e20ecb6be91b304ec3014cbd189976b254500275f5d2bf77ea9a0
3
+ metadata.gz: 987f2b59fff584bde7004887e631c776fd0da367988e6ca6117726ff6b6de937
4
+ data.tar.gz: 41676e4fbcadad6e6a7a2b999368137c4d200fe83da5d7a1a300ed8d0a24a99f
5
5
  SHA512:
6
- metadata.gz: 156c1e465ab38406145f7d3bddf65fa0e40bf28a16109c15eb41f623735032dd23f7ddfb4a3341abbe8167ffd065082aef10945c8181c38bb01c4c368aa1853e
7
- data.tar.gz: 7691712c1641cceb9ed53b6740ad9650844b69056c8433c4b65eb149cc9014ebce8870583306ebe7ed55c23209ec6b762b1a6961225fd65281aa5ddeec133dad
6
+ metadata.gz: 2cda455c10578a6c9b990e0f7c00317166c80d499ff82267a925912935f510b79195d1ad13caf9669af1f314da0dfeb23a7aa9782f3df56996b4a128af3b5535
7
+ data.tar.gz: f394f37f00f3f7dad3abcdfaab5697e1cf2079733a9e385df66101f8e5d1fe55e61f48d385ba9e6d855c9990b509c4a98a63c4efc1e1d9cb2c8535702c1c34cd
@@ -31,8 +31,7 @@ module PgAssociable
31
31
  def collection_pc(atributo, _options)
32
32
  klass = clase_asociacion(atributo)
33
33
  user = Current.user
34
- in_modal = options[:asociable].present?
35
- puede_crear = !in_modal && Pundit::PolicyFinder.new(klass).policy.new(user, klass).new?
34
+ puede_crear = !template.using_modal? && Pundit::PolicyFinder.new(klass).policy.new(user, klass).new?
36
35
  collection = Pundit::PolicyFinder.new(klass).scope.new(user, klass).resolve
37
36
  [collection, puede_crear]
38
37
  end
@@ -3,11 +3,10 @@ module PgAssociable
3
3
  MAX_RESULTS = 8
4
4
 
5
5
  def pg_respond_abrir_modal
6
- respond_to do |format|
7
- format.turbo_stream do
8
- render turbo_stream: turbo_stream.append_all('body', partial: 'pg_associable_modal')
9
- end
10
- end
6
+ content = FormModalComponent.new(@clase_modelo.new.decorate)
7
+ .render_in(view_context)
8
+ modal = AsociableModalComponent.new(modal_id: params[:id]).with_content(content)
9
+ render turbo_stream: turbo_stream.append_all('body', modal)
11
10
  end
12
11
 
13
12
  def pg_respond_buscar
@@ -3,7 +3,6 @@ import * as bootstrap from 'bootstrap'
3
3
 
4
4
  export default class extends Controller {
5
5
  static outlets = ['asociable']
6
- static targets = ['response']
7
6
 
8
7
  modalPuntero = null
9
8
 
@@ -15,17 +14,30 @@ export default class extends Controller {
15
14
  })
16
15
  }
17
16
  this.modalPuntero.show()
17
+
18
+ this.element.addEventListener('pg:record-created', (ev) => {
19
+ const el = ev.data
20
+ if (this.asociableOutlets.length > 0) {
21
+ const newObject = JSON.parse(el.dataset.response)
22
+ this.asociableOutlet.completarCampo(newObject)
23
+ ev.stopPropagation()
24
+ }
25
+ this.modalPuntero.hide()
26
+ })
27
+
28
+ this.element.addEventListener('pg:record-updated', (ev) => {
29
+ this.modalPuntero.hide()
30
+ })
31
+
32
+ this.element.addEventListener('pg:record-destroyed', (ev) => {
33
+ this.modalPuntero.hide()
34
+ })
35
+
18
36
  document.addEventListener('turbo:before-cache', () => {
19
37
  this.element.remove()
20
38
  }, { once: true })
21
39
  }
22
40
 
23
- responseTargetConnected (e) {
24
- const newObject = JSON.parse(e.dataset.response)
25
- this.asociableOutlet.completarCampo(newObject)
26
- this.element.remove()
27
- }
28
-
29
41
  openModal () {
30
42
  this.modalPuntero.show()
31
43
  }
@@ -17,8 +17,8 @@ describe 'Associable' do
17
17
  find('.cosa_categoria_de_cosa .list-group-item').click
18
18
  fill_in 'categoria_de_cosa_nombre', with: 'la categoría'
19
19
  select 'Completar', from: 'categoria_de_cosa_tipo'
20
- click_on 'Crear Categoría de cosa'
21
- click_on 'Crear Coso'
20
+ click_on 'Agregar Categoría de cosa'
21
+ click_on 'Cargar Coso'
22
22
  expect(page).to have_text 'Creado por'
23
23
  end
24
24
  end
@@ -0,0 +1,14 @@
1
+ class ActionsComponent < ViewComponent::Base
2
+ def initialize(record)
3
+ @record = record.decorate
4
+
5
+ super
6
+ end
7
+
8
+ erb_template <<~ERB
9
+ <div>
10
+ <%= @record.edit_link %>
11
+ <%= @record.destroy_link_redirect %>
12
+ </div>
13
+ ERB
14
+ end
@@ -0,0 +1,6 @@
1
+ .modal[class="#{@klass} modal-#{@modal_id}" tabindex="-1" data-controller="modal"
2
+ data-modal-asociable-outlet=".asociable-#{@modal_id}"
3
+ data-turbo-temporary="true"]
4
+ .modal-dialog
5
+ .modal-content
6
+ = content
@@ -0,0 +1,7 @@
1
+ class AsociableModalComponent < ModalComponent
2
+ def initialize(modal_id: nil, **)
3
+ @modal_id = modal_id
4
+
5
+ super(**)
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ = render ModalContentComponent.new do |content|
2
+ - content.with_header do
3
+ / TODO: render breadcrumbs?
4
+ - if @record.persisted?
5
+ = link_to @record.target_object do
6
+ | Ir al #{@record.class.nombre_singular.downcase}
7
+ span.ms-1 » Modificando
8
+ - else
9
+ .fs-5 = @record.decorate.submit_default_value
10
+
11
+ / - content.with_actions do
12
+ = render @record.actions_component
13
+
14
+ - content.with_body do
15
+ = render partial: 'form', locals: { object: @record }
@@ -0,0 +1,6 @@
1
+ class FormModalComponent < ViewComponent::Base
2
+ def initialize(record)
3
+ @record = record
4
+ super
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ .modal[class="#{@klass}" tabindex="-1" data-controller="modal"
2
+ data-remove-on-hide="true" data-turbo-temporary="true"]
3
+ .modal-dialog
4
+ .modal-content
5
+ = content
@@ -0,0 +1,11 @@
1
+ class ModalComponent < ViewComponent::Base
2
+ def initialize(klass: 'modal-xl')
3
+ @klass = klass
4
+
5
+ super
6
+ end
7
+
8
+ def before_render
9
+ controller.instance_variable_set(:@using_modal, true)
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ class ModalContentComponent < ViewComponent::Base
2
+ renders_one :actions
3
+ renders_one :body
4
+ renders_one :header
5
+
6
+ def before_render
7
+ controller.instance_variable_set(:@using_modal, true)
8
+ end
9
+
10
+ erb_template <<~ERB
11
+ <%= helpers.turbo_frame_tag :modal_generic do %>
12
+ <div class="modal-header">
13
+ <%= header %>
14
+ <a class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Close"></a>
15
+ </div>
16
+ <div class="modal-body">
17
+ <div class="d-flex justify-content-around sticky-top">
18
+ <div class="flash position-relative w-100 d-flex justify-content-center">
19
+ </div>
20
+ </div>
21
+ <div class="float-end">
22
+ <%= actions %>
23
+ </div>
24
+ <%= body %>
25
+ </div>
26
+ <% end %>
27
+ ERB
28
+ end
@@ -0,0 +1,10 @@
1
+ = render ModalContentComponent.new do |content|
2
+ - content.with_header do
3
+ = link_to @record.target_object, 'data-turbo-frame': '_top' do
4
+ | Ir al #{@record.class.nombre_singular.downcase}
5
+
6
+ - content.with_actions do
7
+ = render @record.actions_component
8
+
9
+ - content.with_body do
10
+ = render @record
@@ -0,0 +1,7 @@
1
+ class ShowModalComponent < ViewComponent::Base
2
+ def initialize(record, **)
3
+ @record = record
4
+
5
+ super(**)
6
+ end
7
+ end
@@ -14,26 +14,9 @@ module Admin
14
14
 
15
15
  add_breadcrumb Email.nombre_plural, :admin_emails_path
16
16
 
17
- def new
18
- render template: 'admin/emails/_send', locals: { email: @email },
19
- layout: 'pg_layout/containerized'
20
- end
21
-
22
- def create
23
- saved = false
24
- ActiveRecord::Base.transaction do
25
- # TODO: acá la transaction jode porque el ActiveJob no puede deserializar el Email
26
- # Con rails 7.2 esto se debería arreglar
27
- if (saved = @email.save)
28
- PgEngine::AdminMailer.with(email_object: @email).admin_mail.deliver_later
29
- end
30
- end
31
- if saved
32
- redirect_to @email.decorate.target_object
33
- else
34
- render template: 'admin/emails/_send',
35
- layout: 'pg_layout/containerized', status: :unprocessable_entity,
36
- locals: { email: @email }
17
+ after_action only: :create do
18
+ if @saved
19
+ PgEngine::AdminMailer.with(email_object: @email).admin_mail.deliver_later
37
20
  end
38
21
  end
39
22
 
@@ -7,6 +7,16 @@ module PgEngine
7
7
  clazz.helper_method :current_page_size
8
8
  clazz.helper_method :show_filters?
9
9
  clazz.helper_method :available_page_sizes
10
+
11
+ clazz.layout :set_layout
12
+ end
13
+
14
+ def set_layout
15
+ if action_name == 'index'
16
+ 'pg_layout/base'
17
+ else
18
+ 'pg_layout/containerized'
19
+ end
10
20
  end
11
21
 
12
22
  # Public endpoints
@@ -25,18 +35,40 @@ module PgEngine
25
35
  end
26
36
 
27
37
  def show
28
- add_breadcrumb instancia_modelo.to_s_short, instancia_modelo.target_object
29
-
30
38
  pg_respond_show
31
39
  end
32
40
 
41
+ def respond_with_modal(klass_or_string)
42
+ if klass_or_string.is_a?(Class)
43
+ content = klass_or_string.new(instancia_modelo).render_in(view_context)
44
+ elsif klass_or_string.is_a?(String)
45
+ content = ModalContentComponent.new.with_body_content(klass_or_string)
46
+ .render_in(view_context)
47
+ end
48
+
49
+ if can_open_modal?
50
+ modal = ModalComponent.new.with_content(content)
51
+ render turbo_stream: turbo_stream.append_all('body', modal)
52
+ else
53
+ render html: content
54
+ end
55
+ end
56
+
33
57
  def new
34
- add_breadcrumb instancia_modelo.submit_default_value
58
+ if respond_with_modal?
59
+ respond_with_modal(FormModalComponent)
60
+ else
61
+ add_breadcrumb instancia_modelo.submit_default_value
62
+ end
35
63
  end
36
64
 
37
65
  def edit
38
- add_breadcrumb instancia_modelo.to_s_short, instancia_modelo.target_object
39
- add_breadcrumb 'Editando'
66
+ if respond_with_modal?
67
+ respond_with_modal(FormModalComponent)
68
+ else
69
+ add_breadcrumb instancia_modelo.to_s_short, instancia_modelo.target_object
70
+ add_breadcrumb 'Editando'
71
+ end
40
72
  end
41
73
 
42
74
  def create
@@ -93,57 +125,53 @@ module PgEngine
93
125
 
94
126
  def pg_respond_update
95
127
  object = instancia_modelo
96
- respond_to do |format|
97
- if (@saved = object.save)
98
- format.html { redirect_to object.decorate.target_object }
99
- format.json { render json: object.decorate }
128
+ if (@saved = object.save)
129
+ if in_modal?
130
+ body = <<~HTML.html_safe
131
+ <pg-event data-event-name="pg:record-created" data-turbo-temporary
132
+ data-response='#{object.decorate.to_json}'></pg-event>
133
+ HTML
134
+ render html: ModalContentComponent.new.with_body_content(body)
135
+ .render_in(view_context)
100
136
  else
101
- # TODO: esto solucionaría el problema?
102
- # self.instancia_modelo = instancia_modelo.decorate
103
- format.html { render :edit, status: :unprocessable_entity }
104
- format.json { render json: object.errors, status: :unprocessable_entity }
137
+ redirect_to object.decorate.target_object
105
138
  end
139
+ elsif in_modal?
140
+ render html: FormModalComponent.new(instancia_modelo.decorate)
141
+ .render_in(view_context)
142
+ else
143
+ add_breadcrumb instancia_modelo.decorate.to_s_short, instancia_modelo.decorate.target_object
144
+ add_breadcrumb 'Editando'
145
+ # TODO: esto solucionaría el problema?
146
+ # self.instancia_modelo = instancia_modelo.decorate
147
+ #
148
+ render :edit, status: :unprocessable_entity
106
149
  end
107
150
  end
108
151
 
109
152
  def pg_respond_create
110
153
  object = instancia_modelo
111
- respond_to do |format|
112
- if (@saved = object.save)
113
- # TODO: 'asociable' lo cambiaría por 'in_modal' o algo así
114
- if params[:asociable]
115
- format.turbo_stream do
116
- render turbo_stream:
117
- turbo_stream.update_all('.modal.show .pg-associable-form', <<~HTML
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 }
154
+ if (@saved = object.save)
155
+ if in_modal?
156
+ body = <<~HTML.html_safe
157
+ <pg-event data-event-name="pg:record-created" data-turbo-temporary
158
+ data-response='#{object.decorate.to_json}'></pg-event>
159
+ HTML
160
+ render html: ModalContentComponent.new.with_body_content(body)
161
+ .render_in(view_context)
162
+
134
163
  else
135
- # TODO: esto solucionaría el problema?
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 }
164
+ redirect_to object.decorate.target_object
146
165
  end
166
+ elsif in_modal?
167
+ render html: FormModalComponent.new(instancia_modelo.decorate)
168
+ .render_in(view_context)
169
+ else
170
+ add_breadcrumb instancia_modelo.decorate.submit_default_value
171
+ # TODO: esto solucionaría el problema?
172
+ # self.instancia_modelo = instancia_modelo.decorate
173
+
174
+ render :new, status: :unprocessable_entity
147
175
  end
148
176
  end
149
177
 
@@ -159,83 +187,87 @@ module PgEngine
159
187
  end
160
188
  end
161
189
 
162
- def pg_respond_show(object = nil)
163
- object ||= instancia_modelo
164
- if params[:modal].present?
165
- respond_to do |format|
166
- format.html
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
190
+ def accepts_turbo_stream?
191
+ request.headers['Accept'].present? &&
192
+ request.headers['Accept'].include?('text/vnd.turbo-stream.html')
193
+ end
194
+
195
+ def in_modal?
196
+ request.headers['turbo-frame'] == 'modal_generic'
197
+ end
198
+
199
+ def respond_with_modal?
200
+ can_open_modal? || in_modal?
201
+ end
202
+
203
+ def can_open_modal?
204
+ request.get? &&
205
+ params[:start_modal] == 'true' &&
206
+ accepts_turbo_stream? &&
207
+ !in_modal?
208
+ end
209
+
210
+ def pg_respond_show
211
+ if respond_with_modal?
212
+ respond_with_modal(ShowModalComponent)
173
213
  else
174
- respond_to do |format|
175
- format.json { render json: object }
176
- format.html
177
- end
214
+ add_breadcrumb instancia_modelo.to_s_short, instancia_modelo.target_object
178
215
  end
179
216
  end
180
217
 
218
+ def destroyed_message(model)
219
+ "#{model.model_name.human} #{model.gender == 'f' ? 'borrada' : 'borrado'}"
220
+ end
221
+
181
222
  def pg_respond_destroy(model, redirect_url = nil)
182
223
  if destroy_model(model)
183
- msg = "#{model.model_name.human} #{model.gender == 'f' ? 'borrada' : 'borrado'}"
184
- respond_to do |format|
185
- if redirect_url.present?
186
- format.html do
187
- redirect_to redirect_url, notice: msg, status: :see_other
188
- end
189
- else
190
- format.turbo_stream do
191
- # Esto no es totalmente limpio pero funciona tanto en los listados como en los
192
- # modal show
193
- render turbo_stream: turbo_stream.remove(model) + turbo_stream.remove_all('.modal')
194
- end
195
- format.html do
196
- redirect_back(fallback_location: root_path, notice: msg, status: 303)
197
- end
198
- format.json { head :no_content }
199
- end
224
+ if respond_with_modal?
225
+ body = <<~HTML.html_safe
226
+ <pg-event data-event-name="pg:record-destroyed" data-turbo-temporary>
227
+ </pg-event>
228
+ HTML
229
+ respond_with_modal(body)
230
+ elsif redirect_url.present?
231
+ redirect_to redirect_url, notice: destroyed_message(model), status: :see_other
232
+ elsif accepts_turbo_stream?
233
+ body = <<~HTML.html_safe
234
+ <pg-event data-event-name="pg:record-destroyed" data-turbo-temporary>
235
+ </pg-event>
236
+ HTML
237
+ render turbo_stream: turbo_stream.append_all('body', body)
238
+ else
239
+ redirect_back(fallback_location: root_path,
240
+ notice: destroyed_message(model), status: 303)
200
241
  end
242
+ elsif in_modal?
243
+
244
+ flash.now[:alert] = @error_message
245
+ render turbo_stream: render_turbo_stream_flash_messages(to: '.modal-body .flash')
246
+ elsif accepts_turbo_stream?
247
+ flash.now[:alert] = @error_message
248
+ render turbo_stream: render_turbo_stream_flash_messages
201
249
  else
202
- respond_to do |format|
203
- format.html do
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
250
+ flash[:alert] = @error_message
251
+ redirect_back(fallback_location: root_path, status: 303)
214
252
  end
215
253
  end
216
254
 
217
- # TODO: crear esta vista en pg_rails
218
- def destroy_error_details_view
219
- 'destroy_error_details'
220
- end
221
-
222
255
  def destroy_model(model)
223
256
  @error_message = 'No se pudo eliminar el registro'
257
+
224
258
  begin
225
259
  destroy_method = model.respond_to?(:discard) ? :discard : :destroy
226
260
  return true if model.send(destroy_method)
227
261
 
228
- @error_message = model.errors.full_messages.join(', ')
262
+ @error_message = model.errors.full_messages.join(', ').presence || @error_message
263
+
229
264
  false
230
265
  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
266
  model_name = t("activerecord.models.#{model.class.name.underscore}")
236
267
  @error_message = "#{model_name} no se pudo borrar porque tiene elementos asociados."
237
- logger.debug e.message
268
+ pg_warn(e)
238
269
  end
270
+
239
271
  false
240
272
  end
241
273
 
@@ -42,7 +42,11 @@ module PgEngine
42
42
  # rubocop:enable Style/MissingRespondToMissing
43
43
 
44
44
  def destroy_link_redirect
45
- destroy_link(redirect_to: helpers.url_for(target_index))
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
52
  def destroy_link(confirm_text: '¿Estás seguro?', klass: 'btn-light', redirect_to: nil)
@@ -60,18 +64,28 @@ module PgEngine
60
64
  def edit_link(text: ' Modificar', klass: 'btn-warning')
61
65
  return unless Pundit.policy!(Current.user, object).edit?
62
66
 
67
+ start_modal = !helpers.using_modal? && object.class.default_modal
68
+
63
69
  helpers.content_tag :span, rel: :tooltip, title: 'Modificar' do
64
- helpers.link_to edit_object_url, class: "btn btn-sm #{klass}" do
70
+ helpers.link_to edit_object_url + url_suffix(start_modal:), class: "btn btn-sm #{klass}",
71
+ 'data-turbo-stream': start_modal do
65
72
  helpers.content_tag(:span, nil, class: clase_icono('pencil')) + text
66
73
  end
67
74
  end
68
75
  end
69
76
 
77
+ def url_suffix(start_modal: nil)
78
+ start_modal ? '?start_modal=true' : ''
79
+ end
80
+
70
81
  def show_link(text: '', klass: 'btn-light')
71
82
  return unless Pundit.policy!(Current.user, object).show?
72
83
 
84
+ start_modal = !helpers.using_modal? && object.class.default_modal
85
+
73
86
  helpers.content_tag :span, rel: :tooltip, title: 'Ver' do
74
- helpers.link_to object_url, class: "btn btn-sm #{klass}" do
87
+ helpers.link_to object_url + url_suffix(start_modal:), class: "btn btn-sm #{klass}",
88
+ 'data-turbo-stream': start_modal do
75
89
  helpers.content_tag(:span, nil, class: clase_icono('eye-fill')) + text
76
90
  end
77
91
  end
@@ -88,12 +102,14 @@ module PgEngine
88
102
  end
89
103
  end
90
104
 
91
- def new_link(remote: nil, klass: 'btn-warning')
105
+ def new_link(klass: 'btn-warning')
92
106
  return unless Pundit.policy!(Current.user, object).new?
93
107
 
108
+ start_modal = !helpers.using_modal? && object.class.default_modal
109
+
94
110
  helpers.content_tag :span, rel: :tooltip, title: submit_default_value do
95
- helpers.link_to(new_object_url, class: "btn btn-sm #{klass}",
96
- remote:) do
111
+ helpers.link_to(new_object_url + url_suffix(start_modal:), class: "btn btn-sm #{klass}",
112
+ 'data-turbo-stream': start_modal) do
97
113
  helpers.content_tag(:span, nil,
98
114
  class: clase_icono('plus').to_s) + "<span class='d-none d-sm-inline'> #{submit_default_value}</span>".html_safe
99
115
  end
@@ -105,7 +121,7 @@ module PgEngine
105
121
  end
106
122
 
107
123
  def new_object_url
108
- "#{helpers.url_for(target_index)}/new"
124
+ helpers.url_for(target_new)
109
125
  end
110
126
 
111
127
  def object_url
@@ -116,6 +132,11 @@ module PgEngine
116
132
  pg_namespace.present? ? [pg_namespace, object] : object
117
133
  end
118
134
 
135
+ def target_new
136
+ mod_name_sing = object.class.model_name.singular.to_sym
137
+ pg_namespace.present? ? [:new, pg_namespace, mod_name_sing] : [:new, mod_name_sing]
138
+ end
139
+
119
140
  def target_index
120
141
  pg_namespace.present? ? [pg_namespace, object.class] : object.class
121
142
  end
@@ -123,7 +144,7 @@ module PgEngine
123
144
  # actionview-7.1.3.2/lib/action_view/helpers/form_helper.rb
124
145
  def submit_default_value
125
146
  key = :create
126
- model = object.model_name.human
147
+ model = object.model_name.human.downcase
127
148
  defaults = []
128
149
  defaults << :"helpers.submit.#{object.model_name.i18n_key}.#{key}"
129
150
  defaults << :"helpers.submit.#{key}"
@@ -1,7 +1,11 @@
1
1
  module PgEngine
2
2
  module FlashHelper
3
- def render_turbo_stream_flash_messages
4
- turbo_stream.prepend 'flash', partial: 'pg_layout/flash'
3
+ def render_turbo_stream_flash_messages(to: nil)
4
+ if to.present?
5
+ turbo_stream.prepend_all to, partial: 'pg_layout/flash'
6
+ else
7
+ turbo_stream.prepend 'flash', partial: 'pg_layout/flash'
8
+ end
5
9
  end
6
10
 
7
11
  def render_turbo_stream_title