pg_rails 7.6.7 → 7.6.9

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: c0c1496f0173c6ee43cc92f45a5ed539ad58b308533f9fb4fe0f04621882d6de
4
- data.tar.gz: 6cc98c258ec0b585e705162da82386cb10f0726800641eafac229bad90759af4
3
+ metadata.gz: 91cd30e1ebe3fd2ec058f38ac2ad843421e8bb65c989aa5c8b5b7597703719f5
4
+ data.tar.gz: ceeaa8d7d5a2e3cfb32b39ff6c5da0b4c497a826685ef35f92be2cade7ad2d28
5
5
  SHA512:
6
- metadata.gz: 6638f89154fb33f4f840cee25e54d4fc7a544a3f7d65505c779e70d1830b360722ddba32b3e4b3b29e027fa04b76c06740ba687411eb95f055d049f9196dedb8
7
- data.tar.gz: d2c19217475e137c8e2a8177a2325e3ac184d634740b580972bdd2be777c8e0ac6b48b2462cd6b7f5ca21c14828d9bb4d8263fe4eedd24421079bc205ecabc8c
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'
@@ -34,6 +34,10 @@ nav[aria-label=breadcrumb] a {
34
34
  border: 1px solid $red;
35
35
  }
36
36
 
37
+ .trix-content figure a:hover {
38
+ text-decoration: underline;
39
+ }
40
+
37
41
  input[disabled] {
38
42
  background-color: #e9e9ed;
39
43
  color: black;
@@ -8,12 +8,6 @@ class InlineComponent < ViewComponent::Base
8
8
  super
9
9
  end
10
10
 
11
- def before_render
12
- return unless controller.in_modal?
13
-
14
- controller.instance_variable_set(:@using_modal, true)
15
- end
16
-
17
11
  SUFIJOS = %i[f text].freeze
18
12
  def unsuffixed(attribute)
19
13
  ret = attribute.to_s.dup
@@ -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]
@@ -1 +1,16 @@
1
- <%= image_tag blob %>
1
+ <figure class="attachment attachment--<%= blob.representable? ? "preview" : "file" %> attachment--<%= blob.filename.extension %>">
2
+ <% if blob.representable? %>
3
+ <%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %>
4
+ <% end %>
5
+
6
+ <%= link_to rails_blob_path(blob) do %>
7
+ <figcaption class="attachment__caption">
8
+ <% if caption = blob.try(:caption) %>
9
+ <%= caption %>
10
+ <% else %>
11
+ <span class="attachment__name"><%= blob.filename %></span>
12
+ <span class="attachment__size"><%= number_to_human_size blob.byte_size %></span>
13
+ <% end %>
14
+ </figcaption>
15
+ <% end %>
16
+ </figure>
@@ -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,6 +5,32 @@ import './elements'
5
5
 
6
6
  import { Turbo } from '@hotwired/turbo-rails'
7
7
 
8
+ import Trix from 'trix'
9
+
10
+ document.addEventListener('trix-before-initialize', (ev) => {
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'
32
+ })
33
+
8
34
  document.addEventListener('pg:record-created', (ev) => {
9
35
  Turbo.visit(window.location)
10
36
  setTimeout(() => {
@@ -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.7'
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.7
4
+ version: 7.6.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martín Rosso