pg_rails 7.6.8 → 7.6.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61bc441e108885c9686261c08fc110a3096fd0da5f43b78c5b995f2d6a0ae69b
4
- data.tar.gz: b016d6b41b1a814e135c0e15049469ea61c37a056bc4e9545b8946195d0e7164
3
+ metadata.gz: 893c71adcb5816e5cbd09b2860163a03d84c56a4980388578f22ce31dd75e2c6
4
+ data.tar.gz: 8debfcd4a503776a404c284add03df833a2e95efea61ba51e67068203bd72492
5
5
  SHA512:
6
- metadata.gz: 31fc27bf74fce36435f8e23283d5612f893baca07f8d90ac26df6bfe870a7aa74df8b91b116445c680da11e8bebb1db35c7dba2f3ed46ab9ca458d72636f1ca8
7
- data.tar.gz: 0a74fc77e43ef5000cd6acce42f1f48e00bcb07f80847c8a2b3c9c9c2e750ef96dceb51418092f1e3eb75ae160771b4ed4438c524c570dfa8b855a20462f56ba
6
+ metadata.gz: ee18015d09a9ab2940295018f8cb5e8feb2bebb015e90b18984971f6194360cb205b614d5649155df68cbc619f173f3dcb46c9df6aa4f3f3166a00841cb244ef
7
+ data.tar.gz: 77223fb87d0035b0165b4c0edf47830dfc5493a07ec567bc6628a8c3d3407dc2d16030b03d5502d310f8fbf0d2602293b1b63c82d0912166186449798db3beed
@@ -82,17 +82,26 @@
82
82
  .sub-wrapper {
83
83
  overflow: auto;
84
84
  box-shadow: 0px 9px 13px -3px rgba(0, 0, 0, 0.5);
85
+ z-index: 50;
85
86
  // position: absolute;
86
87
  // z-index: 1;
87
88
  background-color: #{$body-bg};
88
89
  border: 1px solid #a7b7bb;
89
90
  border-top: none;
90
91
  border-radius: 4px;
91
- padding: 5px 0;
92
+ // padding: 5px 0;
92
93
  width: 100%;
93
94
 
94
95
  border-top-left-radius: 0;
95
96
  border-top-right-radius: 0;
97
+
98
+ a[data-action="asociable#crearItem"] {
99
+ position: sticky;
100
+ bottom: 0;
101
+ background-color: #faf5ff;
102
+ outline: 1px solid #ababcc;
103
+ box-shadow: 20px 9px 13px 7px rgba(0, 0, 0, 0.5);
104
+ }
96
105
  }
97
106
  .modal-asociable .modal-footer {
98
107
  justify-content: space-between;
@@ -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)
@@ -27,7 +27,6 @@ export default class extends Controller {
27
27
  this.subWrapper.setAttribute('id', `resultados-inline-${this.elemId}`)
28
28
  this.subWrapper.classList.add('sub-wrapper')
29
29
  this.subWrapper.classList.add('position-absolute')
30
- this.subWrapper.classList.add('z-1')
31
30
  result.appendChild(this.subWrapper)
32
31
  this.input.parentNode.appendChild(result)
33
32
 
@@ -138,16 +137,6 @@ export default class extends Controller {
138
137
  resetResultados () {
139
138
  this.lastValue = null
140
139
  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
140
  if (this.element.dataset.preload) {
152
141
  JSON.parse(this.element.dataset.preload).forEach((object) => {
153
142
  rows.push(
@@ -162,6 +151,18 @@ export default class extends Controller {
162
151
  )
163
152
  })
164
153
  }
154
+ if (this.element.dataset.puedeCrear) {
155
+ rows.push(
156
+ <a key="new" href="javascript:void(0)"
157
+ className="list-group-item mt-3 text-center"
158
+ data-action="asociable#crearItem"
159
+ >
160
+ <i className="bi bi-stars"/>
161
+ &nbsp;
162
+ {this.element.dataset.puedeCrear}
163
+ </a>
164
+ )
165
+ }
165
166
  this.subWrapper.innerHTML = renderToStaticMarkup(
166
167
  <div className="resultados" tabIndex={-1}>
167
168
  <ul className="list-group list-group-flush">
@@ -279,7 +280,6 @@ export default class extends Controller {
279
280
  <input type="hidden" name="id" value={this.elemId} />
280
281
  <input type="hidden" name="query" value={this.input.value} />
281
282
  <input type="hidden" name="timeout_id" value={timeouts} />
282
- <input type="hidden" name="puede_crear" value={this.element.dataset.puedeCrear} />
283
283
  </form>
284
284
  )
285
285
  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.text-secondary.pt-1 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'
@@ -211,6 +211,10 @@ input[type=datetime-local], input[type=datetime] {
211
211
  border-bottom: 1px dotted #333;
212
212
  padding-bottom: 1px;
213
213
 
214
+ .edit-link {
215
+ color: rgba(33, 37, 41, 0.21);
216
+ }
217
+
214
218
  &:not(:has(.trix-content)) .edit-link {
215
219
  margin-right: 0.25em;
216
220
  }
@@ -221,8 +225,8 @@ input[type=datetime-local], input[type=datetime] {
221
225
  border-bottom: 1px dotted #333;
222
226
  }
223
227
 
224
- a:hover {
225
- i {
228
+ &:hover {
229
+ .edit-link i {
226
230
  color: black;
227
231
  }
228
232
  }
@@ -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
@@ -4,7 +4,7 @@
4
4
  data: { \
5
5
  controller: :tooltip,
6
6
  'bs-title': "Modificar #{@model.class.human_attribute_name(@attribute).downcase}" },
7
- class: 'text-body-tertiary edit-link', style: 'font-size: 0.8em' do
7
+ class: 'edit-link', style: 'font-size: 0.8em' do
8
8
  i.bi.bi-pencil
9
9
  span = @model.decorate.send(@attribute)
10
10
  - else
@@ -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.10'
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.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martín Rosso