pg_rails 7.3.0 → 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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/pg_associable/app/helpers/pg_associable/form_builder_methods.rb +8 -0
  3. data/pg_associable/app/helpers/pg_associable/helpers.rb +2 -2
  4. data/pg_associable/app/javascript/modal_controller.js +66 -4
  5. data/pg_associable/spec/system/associable_spec.rb +28 -5
  6. data/pg_engine/app/assets/stylesheets/pg_rails_b5.scss +5 -0
  7. data/pg_engine/app/components/date_selector_component.rb +2 -2
  8. data/pg_engine/app/components/modal_content_component.rb +20 -19
  9. data/pg_engine/app/components/search_bar_component.html.slim +1 -1
  10. data/pg_engine/app/controllers/admin/accounts_controller.rb +1 -1
  11. data/pg_engine/app/controllers/admin/email_logs_controller.rb +1 -1
  12. data/pg_engine/app/controllers/admin/emails_controller.rb +1 -1
  13. data/pg_engine/app/controllers/admin/user_accounts_controller.rb +1 -1
  14. data/pg_engine/app/controllers/admin/users_controller.rb +1 -1
  15. data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +209 -86
  16. data/pg_engine/app/controllers/pg_engine/base_controller.rb +5 -0
  17. data/pg_engine/app/controllers/public/mensaje_contactos_controller.rb +1 -1
  18. data/pg_engine/app/decorators/pg_engine/base_record_decorator.rb +24 -19
  19. data/pg_engine/app/helpers/pg_engine/form_helper.rb +0 -5
  20. data/pg_engine/app/helpers/pg_engine/frame_helper.rb +52 -0
  21. data/pg_engine/app/lib/pg_engine/bootstrap5_breadcrumbs_builder.rb +22 -0
  22. data/pg_engine/app/lib/pg_engine/filtros_builder.rb +3 -2
  23. data/pg_engine/app/models/current.rb +1 -1
  24. data/pg_engine/app/models/pg_engine/base_record.rb +2 -0
  25. data/pg_engine/app/views/pg_engine/base/edit.html.slim +1 -2
  26. data/pg_engine/app/views/pg_engine/base/index.html.slim +2 -3
  27. data/pg_engine/config/initializers/ransack_memory.rb +13 -2
  28. data/pg_engine/config/locales/es.yml +1 -1
  29. data/pg_engine/spec/controllers/concerns/pg_engine/resource_helper_spec.rb +0 -2
  30. data/pg_engine/spec/lib/pg_engine/form_helper_spec.rb +0 -2
  31. data/pg_engine/spec/system/breadcrumbs_spec.rb +61 -0
  32. data/pg_engine/spec/system/destroy_spec.rb +1 -1
  33. data/pg_engine/spec/system/login_spec.rb +1 -1
  34. data/pg_engine/spec/system/modal_windows_spec.rb +4 -4
  35. data/pg_layout/app/javascript/application.js +14 -0
  36. data/pg_layout/app/javascript/config/turbo_rails/index.js +4 -1
  37. data/pg_layout/app/javascript/controllers/embedded_frame_controller.js +10 -0
  38. data/pg_layout/app/javascript/controllers/index.js +2 -0
  39. data/pg_layout/app/javascript/controllers/tooltip_controller.js +8 -0
  40. data/pg_layout/app/javascript/elements/pg_event.js +2 -1
  41. data/pg_layout/app/views/layouts/pg_layout/base.html.slim +45 -17
  42. data/pg_layout/app/views/layouts/pg_layout/containerized.html.slim +1 -1
  43. data/pg_rails/lib/version.rb +1 -1
  44. data/pg_rails/scss/bootstrap_overrides.scss +2 -1
  45. data/pg_rails/scss/pg_rails.scss +8 -1
  46. data/pg_scaffold/lib/generators/pg_scaffold/templates/controller.rb +2 -4
  47. metadata +6 -6
  48. data/pg_engine/app/components/form_modal_component.html.slim +0 -15
  49. data/pg_engine/app/components/form_modal_component.rb +0 -6
  50. data/pg_engine/app/components/show_modal_component.html.slim +0 -10
  51. data/pg_engine/app/components/show_modal_component.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 987f2b59fff584bde7004887e631c776fd0da367988e6ca6117726ff6b6de937
4
- data.tar.gz: 41676e4fbcadad6e6a7a2b999368137c4d200fe83da5d7a1a300ed8d0a24a99f
3
+ metadata.gz: ad67165e1aad7f3b3e31dd236706d4b923eb2139740a095018257899b43928a7
4
+ data.tar.gz: f3d907a47d97cb7abbfb0e148bb2c2e9466a5255284f14f06c0363966e35e46b
5
5
  SHA512:
6
- metadata.gz: 2cda455c10578a6c9b990e0f7c00317166c80d499ff82267a925912935f510b79195d1ad13caf9669af1f314da0dfeb23a7aa9782f3df56996b4a128af3b5535
7
- data.tar.gz: f394f37f00f3f7dad3abcdfaab5697e1cf2079733a9e385df66101f8e5d1fe55e61f48d385ba9e6d855c9990b509c4a98a63c4efc1e1d9cb2c8535702c1c34cd
6
+ metadata.gz: 3d8482db6b3b8455c819d4db06db374e40785cec70a9737bfca652c2368bddad17ca7a2d3656e1632b48b0ebeb03c5142e83855d3d70cfd9d043de3e7d34609d
7
+ data.tar.gz: e6e2457ac2a84097209da469aa76dd2538e72c9da05ed383884c19fceddc071b5dc515a82c444c4f3487d7912ca79790bd6eb06f0eed0ae0c4caf48e8797884f
@@ -16,6 +16,14 @@ module PgAssociable
16
16
  end
17
17
 
18
18
  def pg_associable(atributo, options = {})
19
+ # Si es new y tiene el nested asignado, no permito que se modifique
20
+ # porque de todos modos se pisaría en el create
21
+ if !object.persisted? &&
22
+ template.nested_record.present? &&
23
+ object.send(template.nested_key) == (template.nested_record.id)
24
+ options[:disabled] = true
25
+ end
26
+
19
27
  return input(atributo, options) if options[:disabled]
20
28
 
21
29
  collection, puede_crear = collection_pc(atributo, options)
@@ -3,8 +3,8 @@ module PgAssociable
3
3
  MAX_RESULTS = 8
4
4
 
5
5
  def pg_respond_abrir_modal
6
- content = FormModalComponent.new(@clase_modelo.new.decorate)
7
- .render_in(view_context)
6
+ src = @clase_modelo.new.decorate.new_object_url
7
+ content = ModalContentComponent.new(src:).render_in(view_context)
8
8
  modal = AsociableModalComponent.new(modal_id: params[:id]).with_content(content)
9
9
  render turbo_stream: turbo_stream.append_all('body', modal)
10
10
  end
@@ -5,6 +5,7 @@ export default class extends Controller {
5
5
  static outlets = ['asociable']
6
6
 
7
7
  modalPuntero = null
8
+ history = []
8
9
 
9
10
  connect (e) {
10
11
  this.modalPuntero = new bootstrap.Modal(this.element)
@@ -15,22 +16,30 @@ export default class extends Controller {
15
16
  }
16
17
  this.modalPuntero.show()
17
18
 
19
+ this.element.addEventListener('turbo:frame-render', (ev) => {
20
+ if (ev.detail.fetchResponse.response.ok && ev.target.id === 'modal_content') {
21
+ this.history.push(ev.target.src)
22
+ }
23
+ })
24
+
18
25
  this.element.addEventListener('pg:record-created', (ev) => {
19
26
  const el = ev.data
20
27
  if (this.asociableOutlets.length > 0) {
21
28
  const newObject = JSON.parse(el.dataset.response)
22
29
  this.asociableOutlet.completarCampo(newObject)
23
30
  ev.stopPropagation()
31
+ this.remove()
32
+ } else {
33
+ this.back(ev)
24
34
  }
25
- this.modalPuntero.hide()
26
35
  })
27
36
 
28
37
  this.element.addEventListener('pg:record-updated', (ev) => {
29
- this.modalPuntero.hide()
38
+ this.back(ev)
30
39
  })
31
40
 
32
41
  this.element.addEventListener('pg:record-destroyed', (ev) => {
33
- this.modalPuntero.hide()
42
+ this.remove()
34
43
  })
35
44
 
36
45
  document.addEventListener('turbo:before-cache', () => {
@@ -38,12 +47,65 @@ export default class extends Controller {
38
47
  }, { once: true })
39
48
  }
40
49
 
50
+ maximize (ev) {
51
+ const dialog = this.element.querySelector('.modal-dialog')
52
+ dialog.classList.toggle('modal-fullscreen')
53
+ const button = ev.currentTarget
54
+ const icon = button.querySelector('i')
55
+ icon.classList.toggle('bi-fullscreen')
56
+ icon.classList.toggle('bi-fullscreen-exit')
57
+
58
+ const tooltip = this.application.getControllerForElementAndIdentifier(button, 'tooltip')
59
+ if (tooltip) {
60
+ tooltip.hide()
61
+ if (icon.classList.contains('bi-fullscreen')) {
62
+ tooltip.setContent('Maximizar')
63
+ } else {
64
+ tooltip.setContent('Restaurar')
65
+ }
66
+ }
67
+ }
68
+
69
+ reloadTop () {
70
+ // FIXME: rename to main?
71
+ const topFrame = document.querySelector('#top')
72
+ if (topFrame.attributes.src) {
73
+ topFrame.reload()
74
+ } else {
75
+ topFrame.setAttribute('src', window.location)
76
+ }
77
+ }
78
+
79
+ back (ev) {
80
+ this.history.pop()
81
+ if (this.history.length > 0) {
82
+ const url = this.history[this.history.length - 1]
83
+ const frame = this.element.querySelector('#modal_content')
84
+ frame.src = url
85
+ frame.innerHTML = '<div style="min-height: 30em">Cargando...</div>'
86
+ } else {
87
+ this.modalPuntero.hide()
88
+ }
89
+ ev.stopPropagation()
90
+ this.reloadTop()
91
+ }
92
+
41
93
  openModal () {
42
94
  this.modalPuntero.show()
43
95
  }
44
96
 
97
+ remove () {
98
+ this.element.remove()
99
+ }
100
+
45
101
  disconnect (e) {
46
- this.modalPuntero.hide()
102
+ // Antes, en lugar de quitar el modal-backdrop:
103
+ // this.modalPuntero.hide()
104
+ // pero tiraba a veces error:
105
+ // TypeError: can't convert null to object, _isWithActiveTrigger
106
+ document.querySelectorAll('.modal-backdrop').forEach((el) => {
107
+ el.remove()
108
+ })
47
109
  document.dispatchEvent(new Event('hidden.bs.modal'))
48
110
  this.modalPuntero.dispose()
49
111
  }
@@ -3,16 +3,17 @@ require 'rails_helper'
3
3
  describe 'Associable' do
4
4
  let(:user) { create :user, :developer }
5
5
 
6
+ let(:path) { '/admin/cosas/new' }
7
+
6
8
  before do
7
9
  login_as user
8
- driven_by :selenium
9
- visit '/admin/cosas/new'
10
- fill_in 'cosa_nombre', with: 'La cosa'
11
- select 'Los', from: 'cosa_tipo'
12
- find('.cosa_categoria_de_cosa input[type=text]').click
10
+ visit path
13
11
  end
14
12
 
15
13
  it do
14
+ fill_in 'cosa_nombre', with: 'La cosa'
15
+ select 'Los', from: 'cosa_tipo'
16
+ find('.cosa_categoria_de_cosa input[type=text]').click
16
17
  expect(page).to have_text :all, 'Nuevo'
17
18
  find('.cosa_categoria_de_cosa .list-group-item').click
18
19
  fill_in 'categoria_de_cosa_nombre', with: 'la categoría'
@@ -21,4 +22,26 @@ describe 'Associable' do
21
22
  click_on 'Cargar Coso'
22
23
  expect(page).to have_text 'Creado por'
23
24
  end
25
+
26
+ context 'cuando crea desde el nested' do
27
+ let!(:categ) { create :categoria_de_cosa }
28
+ let(:path) { "/admin/categoria_de_cosas/#{categ.hashid}/cosas/new" }
29
+
30
+ it do
31
+ input = find_by_id('cosa_categoria_de_cosa')
32
+ expect(input).to be_disabled
33
+ end
34
+ end
35
+
36
+ context 'cuando edita desde el nested' do
37
+ let!(:categ) { create :categoria_de_cosa }
38
+ let!(:cosa) { create :cosa, categoria_de_cosa: categ }
39
+ let(:path) { "/admin/categoria_de_cosas/#{categ.hashid}/cosas/#{cosa.id}/edit" }
40
+
41
+ it do
42
+ ele = find_by_id('cosa_categoria_de_cosa_id', visible: :all)
43
+ input = ele.sibling('input[type=text]')
44
+ expect(input).not_to be_disabled
45
+ end
46
+ end
24
47
  end
@@ -9,6 +9,11 @@
9
9
  --bs-form-invalid-border-color: #b50000;
10
10
  }
11
11
 
12
+ // Navs
13
+ nav[aria-label=breadcrumb] a {
14
+ font-weight: bold;
15
+ }
16
+
12
17
  // Toasts
13
18
  .toast.show {
14
19
  display: inline-block;
@@ -3,9 +3,9 @@ class DateSelectorComponent < ViewComponent::Base
3
3
  @field_id = field_id
4
4
 
5
5
  @types = [
6
- ['Días corridos (L a D)', 'calendar_days'],
7
- ['Días hábiles (L a V)', 'business_days'],
8
6
  ['Días hábiles no feriados', 'business_days_excluding_holidays'],
7
+ ['Días hábiles (L a V)', 'business_days'],
8
+ ['Días corridos (L a D)', 'calendar_days'],
9
9
  ['Semanas', 'weeks'],
10
10
  ['Meses', 'months']
11
11
  ]
@@ -1,28 +1,29 @@
1
1
  class ModalContentComponent < ViewComponent::Base
2
- renders_one :actions
3
- renders_one :body
4
- renders_one :header
2
+ def initialize(src: nil)
3
+ @src = src
4
+ with_content(loading_html) if @src.present?
5
5
 
6
- def before_render
7
- controller.instance_variable_set(:@using_modal, true)
6
+ super
8
7
  end
9
8
 
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>
9
+ def loading_html
10
+ <<~HTML.html_safe
11
+ <div class="text-center text-body-secondary fs-3" style="min-height: 15em">
12
+ Cargando...
15
13
  </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 %>
14
+ HTML
15
+ end
16
+
17
+ erb_template <<~ERB
18
+ <div class="modal-body">
19
+ <div class="d-flex justify-content-around sticky-top">
20
+ <div class="flash position-relative w-100 d-flex justify-content-center">
23
21
  </div>
24
- <%= body %>
25
22
  </div>
26
- <% end %>
23
+ <%= helpers.turbo_frame_tag :modal_content,
24
+ **{ src: @src, refresh: :morph }.compact do %>
25
+ <%= content %>
26
+ <% end %>
27
+ </div>
27
28
  ERB
28
29
  end
@@ -3,7 +3,7 @@
3
3
  .d-flex.align-items-center.px-3.py-2
4
4
  .px-2.d-none.d-sm-inline-block
5
5
  span.bi.bi-funnel-fill
6
- = helpers.search_form_for @q, url: url_for, html: { 'data-turbo-action': :advance } do |f|
6
+ = helpers.search_form_for @q, url: url_for do |f|
7
7
  .row.g-1
8
8
  .col
9
9
  .row.g-1
@@ -6,7 +6,7 @@ module Admin
6
6
  class AccountsController < AdminController
7
7
  include PgEngine::Resource
8
8
 
9
- before_action { @clase_modelo = Account }
9
+ self.clase_modelo = Account
10
10
 
11
11
  before_action(only: :index) { authorize Account }
12
12
 
@@ -6,7 +6,7 @@ module Admin
6
6
  class EmailLogsController < AdminController
7
7
  include PgEngine::Resource
8
8
 
9
- before_action { @clase_modelo = EmailLog }
9
+ self.clase_modelo = EmailLog
10
10
 
11
11
  before_action(only: :index) { authorize EmailLog }
12
12
 
@@ -6,7 +6,7 @@ module Admin
6
6
  class EmailsController < AdminController
7
7
  include PgEngine::Resource
8
8
 
9
- before_action { @clase_modelo = Email }
9
+ self.clase_modelo = Email
10
10
 
11
11
  before_action(only: :index) { authorize Email }
12
12
 
@@ -6,7 +6,7 @@ module Admin
6
6
  class UserAccountsController < AdminController
7
7
  include PgEngine::Resource
8
8
 
9
- before_action { @clase_modelo = UserAccount }
9
+ self.clase_modelo = UserAccount
10
10
 
11
11
  before_action(only: :index) { authorize UserAccount }
12
12
 
@@ -6,7 +6,7 @@ module Admin
6
6
  class UsersController < AdminController
7
7
  include PgEngine::Resource
8
8
 
9
- before_action { @clase_modelo = User }
9
+ self.clase_modelo = User
10
10
 
11
11
  before_action(only: :index) { authorize User }
12
12