pg_rails 7.6.8 → 7.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61bc441e108885c9686261c08fc110a3096fd0da5f43b78c5b995f2d6a0ae69b
4
- data.tar.gz: b016d6b41b1a814e135c0e15049469ea61c37a056bc4e9545b8946195d0e7164
3
+ metadata.gz: 91cd30e1ebe3fd2ec058f38ac2ad843421e8bb65c989aa5c8b5b7597703719f5
4
+ data.tar.gz: ceeaa8d7d5a2e3cfb32b39ff6c5da0b4c497a826685ef35f92be2cade7ad2d28
5
5
  SHA512:
6
- metadata.gz: 31fc27bf74fce36435f8e23283d5612f893baca07f8d90ac26df6bfe870a7aa74df8b91b116445c680da11e8bebb1db35c7dba2f3ed46ab9ca458d72636f1ca8
7
- data.tar.gz: 0a74fc77e43ef5000cd6acce42f1f48e00bcb07f80847c8a2b3c9c9c2e750ef96dceb51418092f1e3eb75ae160771b4ed4438c524c570dfa8b855a20462f56ba
6
+ metadata.gz: 4e4444db810e6836a963c75fa5727c39f434c6032c269671bd9286fca0eb788a3013c45f494cebf2c583df4bc0c37803922d86090bc10685e46fee4b158919aa
7
+ data.tar.gz: a44d48f9d63295bdf519ac6ba424ebc0d1ed1c69f28b5c8be898b1c58dc72165a8ae3b5bb75f4ac47efc13987fba2e134cf275f03a7ac00f9251774f1f387c78
@@ -6,7 +6,7 @@ module PgAssociable
6
6
  mod.include PgEngine::RouteHelper
7
7
  end
8
8
 
9
- MAXIMO_PARA_SELECT = 10
9
+ LIMIT_TO_AUTOPRELOAD = 10
10
10
  # TODO: si está entre 10 y 50, habilitar un buscador por js
11
11
 
12
12
  def pg_associable_pro(atributo, options = {})
@@ -27,15 +27,21 @@ module PgAssociable
27
27
  return input(atributo, options) if options[:disabled]
28
28
 
29
29
  collection, puede_crear = collection_pc(atributo, options)
30
- options.deep_merge!({ wrapper_html: { 'data-puede-crear': 'true' } }) if puede_crear
30
+ collection_count = collection.count
31
+ options.deep_merge!({ wrapper_html: { 'data-puede-crear': text_for_new(atributo) } }) if puede_crear
31
32
 
32
- if !puede_crear && collection.count <= MAXIMO_PARA_SELECT
33
+ if !puede_crear && collection_count <= LIMIT_TO_AUTOPRELOAD
33
34
  select_comun(atributo, options, collection)
34
35
  else
35
- select_pro(atributo, options, collection)
36
+ select_pro(atributo, options, collection, collection_count)
36
37
  end
37
38
  end
38
39
 
40
+ def text_for_new(atributo)
41
+ klass = clase_asociacion(atributo)
42
+ klass.new.decorate.text_for_new
43
+ end
44
+
39
45
  def collection_pc(atributo, _options)
40
46
  klass = clase_asociacion(atributo)
41
47
  user = Current.user
@@ -45,7 +51,12 @@ module PgAssociable
45
51
  [collection, puede_crear]
46
52
  end
47
53
 
48
- def select_pro(atributo, options, collection)
54
+ def select_pro(atributo, options, collection, collection_count = nil)
55
+ if collection_count.present? && collection_count.positive? &&
56
+ collection_count < LIMIT_TO_AUTOPRELOAD && options[:preload].blank?
57
+ options[:preload] = collection
58
+ end
59
+
49
60
  if (preload = options.delete(:preload))
50
61
  collection = preload.is_a?(Integer) ? collection.limit(preload) : preload
51
62
  options.deep_merge!({ wrapper_html: { 'data-preload': collection.decorate.to_json } })
@@ -16,9 +16,10 @@ module PgAssociable
16
16
  query = params[:query]
17
17
  timeout_id = params[:timeout_id]
18
18
  @collection = search_in_scope(query)
19
+ @count = @collection.count
19
20
  render turbo_stream:
20
21
  turbo_stream.update("#{resultados_prefix}-#{params[:id]}",
21
- partial:, locals: { collection: @collection, query:, timeout_id: })
22
+ partial:, locals: { collection: @collection, query:, timeout_id:, count: @count })
22
23
  end
23
24
 
24
25
  def search_in_scope(query)
@@ -138,16 +138,6 @@ export default class extends Controller {
138
138
  resetResultados () {
139
139
  this.lastValue = null
140
140
  const rows = []
141
- if (this.element.dataset.puedeCrear) {
142
- rows.push(
143
- <a key="new" href="javascript:void(0)"
144
- className="list-group-item"
145
- data-action="asociable#crearItem"
146
- >
147
- Nuevo
148
- </a>
149
- )
150
- }
151
141
  if (this.element.dataset.preload) {
152
142
  JSON.parse(this.element.dataset.preload).forEach((object) => {
153
143
  rows.push(
@@ -162,6 +152,18 @@ export default class extends Controller {
162
152
  )
163
153
  })
164
154
  }
155
+ if (this.element.dataset.puedeCrear) {
156
+ rows.push(
157
+ <a key="new" href="javascript:void(0)"
158
+ className="list-group-item mt-3 text-center"
159
+ data-action="asociable#crearItem"
160
+ >
161
+ <i className="bi bi-stars"/>
162
+ &nbsp;
163
+ {this.element.dataset.puedeCrear}
164
+ </a>
165
+ )
166
+ }
165
167
  this.subWrapper.innerHTML = renderToStaticMarkup(
166
168
  <div className="resultados" tabIndex={-1}>
167
169
  <ul className="list-group list-group-flush">
@@ -279,7 +281,6 @@ export default class extends Controller {
279
281
  <input type="hidden" name="id" value={this.elemId} />
280
282
  <input type="hidden" name="query" value={this.input.value} />
281
283
  <input type="hidden" name="timeout_id" value={timeouts} />
282
- <input type="hidden" name="puede_crear" value={this.element.dataset.puedeCrear} />
283
284
  </form>
284
285
  )
285
286
  const form = document.createElement('div')
@@ -1,12 +1,23 @@
1
- / # locals: (collection:, query:, timeout_id:, field_name: nil)
1
+ / # locals: (collection:, query:, timeout_id:, count:, field_name: nil)
2
2
  .resultados.inline tabindex="-1"
3
3
  div data-controller="clear-timeout" data-timeout-id="#{timeout_id}"
4
4
  ul.list-group.list-group-flush
5
- - if collection.any?
5
+ - if count.positive?
6
+ .text-center.fst-italic style="font-size:0.7em"
7
+ | #{count} resultados para "#{query}"
6
8
  - collection.each do |object|
7
9
  = link_to object.to_s, 'javascript:void(0)',
8
10
  class: 'list-group-item',
9
11
  data: { action: 'asociable#selectItem',
10
12
  id: object.id, object: object.decorate.to_json, field_name: }
11
13
  - else
12
- li.px-3.py-1 style="font-size: 0.85em" No hay resultados para "#{query}"
14
+ li [class="list-group-item text-center text-warning-emphasis py-2" style="font-size: 0.85em"]
15
+ | No hay resultados para "#{query}"
16
+
17
+ - if policy(clase_modelo).new_from_associable?
18
+ / TODO: unificar código repetido en asociable_controller.js
19
+ a [key="new" href="javascript:void(0)" class="list-group-item mt-3 text-center"
20
+ data-action="asociable#crearItem"]
21
+ i class="bi bi-stars"
22
+ | &nbsp;
23
+ = clase_modelo.new.decorate.text_for_new
@@ -14,7 +14,7 @@ describe 'Associable' do
14
14
  fill_in 'cosa_nombre', with: 'La cosa'
15
15
  select 'Los', from: 'cosa_tipo'
16
16
  find('.cosa_categoria_de_cosa input[type=text]').click
17
- expect(page).to have_text :all, 'Nuevo'
17
+ expect(page).to have_text :all, 'Nueva categoría de cosa'
18
18
  find('.cosa_categoria_de_cosa .list-group-item').click
19
19
  select Account.first.to_s
20
20
  fill_in 'categoria_de_cosa_nombre', with: 'la categoría'
@@ -1,18 +1,19 @@
1
1
  = helpers.turbo_frame_tag(@frame_id, class: 'inline-edit')
2
- = helpers.pg_form_for(@model, render_errors: false, wrapper_mappings: @wrapper_mappings) do |f|
3
- = hidden_field_tag :inline_attribute, @attribute
2
+ div data-controller="pg_form"
3
+ = helpers.pg_form_for(@model, render_errors: false, wrapper_mappings: @wrapper_mappings) do |f|
4
+ = hidden_field_tag :inline_attribute, @attribute
4
5
 
5
- / html5 solo aplica a datetime
6
- / date_selector solo aplica a date
7
- / ignore_date y prompt solo aplica a time
8
- / cada caso es inocuo para el resto de los types
9
- = f.field @unsuffixed_attribute, label: false, date_selector: true, minute_step: 15,
10
- ignore_date: true, prompt: { hour: 'hh', minute: 'mm' }
11
- .actions.d-flex.gap-1
12
- = button_tag class: 'btn btn-sm btn-primary',
13
- data: { controller: 'tooltip', 'bs-title': 'Guardar' } do
14
- i.bi.bi-check-lg
15
- = link_to users_inline_show_path(model: @model.to_gid, attribute: @attribute),
16
- class: 'btn btn-sm btn-secondary',
17
- data: { controller: 'tooltip', 'bs-title': 'Cancelar' } do
18
- i.bi.bi-x-lg
6
+ / html5 solo aplica a datetime
7
+ / date_selector solo aplica a date
8
+ / ignore_date y prompt solo aplica a time
9
+ / cada caso es inocuo para el resto de los types
10
+ = f.field @unsuffixed_attribute, label: false, date_selector: true, minute_step: 15,
11
+ ignore_date: true, prompt: { hour: 'hh', minute: 'mm' }
12
+ .actions.d-flex.gap-1
13
+ = button_tag class: 'btn btn-sm btn-primary',
14
+ data: { controller: 'tooltip', 'bs-title': 'Guardar' } do
15
+ i.bi.bi-check-lg
16
+ = link_to users_inline_show_path(model: @model.to_gid, attribute: @attribute),
17
+ class: 'btn btn-sm btn-secondary',
18
+ data: { controller: 'tooltip', 'bs-title': 'Cancelar' } do
19
+ i.bi.bi-x-lg
@@ -3,7 +3,7 @@ class InlineEditComponent < InlineComponent
3
3
  @wrapper_mappings = {
4
4
  string: :inline_form_grow,
5
5
  pg_associable: :inline_form_control,
6
- date: :inline_form_control,
6
+ date: :inline_form_control_autosubmit,
7
7
  datetime: :inline_form_control,
8
8
  time: :inline_multi_select,
9
9
  select: :inline_form_select
@@ -26,6 +26,13 @@ module PgEngine
26
26
  truncate(object.to_s)
27
27
  end
28
28
 
29
+ def text_for_new
30
+ klass = object.class
31
+ # TODO: no está bueno tener que hacer el new, gender debería estar en la clase
32
+ verb = klass.new.gender == 'f' ? 'Nueva' : 'Nuevo'
33
+ "#{verb} #{klass.model_name.human.downcase}"
34
+ end
35
+
29
36
  # rubocop:disable Style/MissingRespondToMissing
30
37
  def method_missing(method_name, *args, &)
31
38
  valor = object.attributes[method_name.to_s]
@@ -310,6 +310,21 @@ SimpleForm.setup do |config|
310
310
  b.optional :hint, wrap_with: { class: 'form-text' }
311
311
  end
312
312
 
313
+ config.wrappers :inline_form_control_autosubmit, class: '' do |b|
314
+ b.use :html5
315
+ b.use :placeholder
316
+ b.optional :maxlength
317
+ b.optional :minlength
318
+ b.optional :pattern
319
+ b.optional :min_max
320
+ b.optional :readonly
321
+ b.use :label, class: 'visually-hidden'
322
+
323
+ b.use :input, class: 'form-control form-control-sm', error_class: 'is-invalid', 'data-action': 'pg_form#submit'
324
+ b.use :error, wrap_with: { class: 'invalid-feedback' }
325
+ b.optional :hint, wrap_with: { class: 'form-text' }
326
+ end
327
+
313
328
  config.wrappers :inline_form_select, class: '' do |b|
314
329
  b.use :html5
315
330
  b.use :placeholder
@@ -320,7 +335,7 @@ SimpleForm.setup do |config|
320
335
  b.optional :readonly
321
336
  b.use :label, class: 'visually-hidden'
322
337
 
323
- b.use :input, class: 'form-select form-select-sm', error_class: 'is-invalid'
338
+ b.use :input, class: 'form-select form-select-sm', error_class: 'is-invalid', 'data-action': 'pg_form#submit'
324
339
  b.use :error, wrap_with: { class: 'invalid-feedback' }
325
340
  b.optional :hint, wrap_with: { class: 'form-text' }
326
341
  end
@@ -5,28 +5,30 @@ import './elements'
5
5
 
6
6
  import { Turbo } from '@hotwired/turbo-rails'
7
7
 
8
+ import Trix from 'trix'
9
+
8
10
  document.addEventListener('trix-before-initialize', (ev) => {
9
- Trix.config.lang.attachFiles = "Adjuntar archivos"
10
- Trix.config.lang.bold = "Negrita"
11
- Trix.config.lang.bullets = "Lista sin números"
12
- Trix.config.lang.byte = "Byte"
13
- Trix.config.lang.bytes = "Bytes"
14
- Trix.config.lang.captionPlaceholder = "Agregá un subtítulo"
15
- Trix.config.lang.code = "Monospace"
16
- Trix.config.lang.heading1 = "Título"
17
- Trix.config.lang.indent = "Incrementar nivel"
18
- Trix.config.lang.italic = "Cursiva"
19
- Trix.config.lang.link = "Linkear"
20
- Trix.config.lang.numbers = "Lista numerada"
21
- Trix.config.lang.outdent = "Disminuir nivel"
22
- Trix.config.lang.quote = "Cita"
23
- Trix.config.lang.redo = "Rehacer"
24
- Trix.config.lang.remove = "Quitar"
25
- Trix.config.lang.strike = "Tachar"
26
- Trix.config.lang.undo = "Deshacer"
27
- Trix.config.lang.unlink = "Deslinkear"
28
- Trix.config.lang.url = "URL"
29
- Trix.config.lang.urlPlaceholder = "Ingresá una URL"
11
+ Trix.config.lang.attachFiles = 'Adjuntar archivos'
12
+ Trix.config.lang.bold = 'Negrita'
13
+ Trix.config.lang.bullets = 'Lista sin números'
14
+ Trix.config.lang.byte = 'Byte'
15
+ Trix.config.lang.bytes = 'Bytes'
16
+ Trix.config.lang.captionPlaceholder = 'Agregá un subtítulo'
17
+ Trix.config.lang.code = 'Monospace'
18
+ Trix.config.lang.heading1 = 'Título'
19
+ Trix.config.lang.indent = 'Incrementar nivel'
20
+ Trix.config.lang.italic = 'Cursiva'
21
+ Trix.config.lang.link = 'Linkear'
22
+ Trix.config.lang.numbers = 'Lista numerada'
23
+ Trix.config.lang.outdent = 'Disminuir nivel'
24
+ Trix.config.lang.quote = 'Cita'
25
+ Trix.config.lang.redo = 'Rehacer'
26
+ Trix.config.lang.remove = 'Quitar'
27
+ Trix.config.lang.strike = 'Tachar'
28
+ Trix.config.lang.undo = 'Deshacer'
29
+ Trix.config.lang.unlink = 'Deslinkear'
30
+ Trix.config.lang.url = 'URL'
31
+ Trix.config.lang.urlPlaceholder = 'Ingresá una URL'
30
32
  })
31
33
 
32
34
  document.addEventListener('pg:record-created', (ev) => {
@@ -34,4 +34,19 @@ export default class extends Controller {
34
34
  }
35
35
  }
36
36
  }
37
+
38
+ submit () {
39
+ let form = null
40
+ if (this.element instanceof HTMLFormElement) {
41
+ form = this.element
42
+ } else {
43
+ form = this.element.querySelector('form')
44
+ }
45
+ if (form) {
46
+ form.requestSubmit()
47
+ } else {
48
+ Rollbar.error('No form found')
49
+ console.error('No form found')
50
+ }
51
+ }
37
52
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgRails
4
- VERSION = '7.6.8'
4
+ VERSION = '7.6.9'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.6.8
4
+ version: 7.6.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martín Rosso