pg_rails 7.2.3 → 7.3.0

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.
Files changed (60) 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/popover_toggler_controller.js +3 -2
  46. data/pg_layout/app/javascript/elements/index.js +1 -0
  47. data/pg_layout/app/javascript/elements/pg_event.js +12 -0
  48. data/pg_layout/app/views/devise/confirmations/new.html.erb +0 -1
  49. data/pg_layout/app/views/devise/passwords/edit.html.erb +0 -2
  50. data/pg_layout/app/views/devise/passwords/new.html.erb +0 -2
  51. data/pg_layout/app/views/devise/registrations/edit.html.erb +0 -2
  52. data/pg_layout/app/views/devise/registrations/new.html.erb +0 -2
  53. data/pg_layout/app/views/devise/unlocks/new.html.erb +0 -1
  54. data/pg_rails/lib/version.rb +1 -1
  55. data/pg_scaffold/lib/generators/pg_rspec/scaffold/templates/controller_spec.rb +2 -2
  56. data/pg_scaffold/lib/generators/pg_slim/templates/_form.html.slim +2 -5
  57. data/pg_scaffold/lib/generators/pg_slim/templates/show.html.slim +1 -1
  58. metadata +17 -4
  59. data/pg_associable/app/views/pg_engine/base/_pg_associable_modal.html.slim +0 -14
  60. 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: c2505003e224d063bd2c51742b431b315cef9e83b08c867adb0687f9184ad559
4
- data.tar.gz: 0d3e3c74ef4c00f0e369302a592fccc0749ddb53c7143abd0be4dc1cf7da6418
3
+ metadata.gz: 987f2b59fff584bde7004887e631c776fd0da367988e6ca6117726ff6b6de937
4
+ data.tar.gz: 41676e4fbcadad6e6a7a2b999368137c4d200fe83da5d7a1a300ed8d0a24a99f
5
5
  SHA512:
6
- metadata.gz: 64ee127677a3f745bd0d29b8fac8150b03470d4cd03d6d6b37078168a3bfd43ac3332f085942bb9d0ea94b164fdd863f65df76c116f8e1ff708ebe012ac31348
7
- data.tar.gz: 6cb3a28799ddd2a7c2fb621a1875b246b825355cd0e7b3a66925030138f46b0d81e1d5c0fa22ce29c4c5c747984145076af5a89085891112230ed34ebcd61732
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