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 +4 -4
- data/pg_associable/app/helpers/pg_associable/form_builder_methods.rb +16 -5
- data/pg_associable/app/helpers/pg_associable/helpers.rb +2 -1
- data/pg_associable/app/javascript/asociable_controller.tsx +12 -11
- data/pg_associable/app/views/pg_associable/_resultados_inline.html.slim +14 -3
- data/pg_associable/spec/system/associable_spec.rb +1 -1
- data/pg_engine/app/components/inline_edit/inline_edit_component.html.slim +17 -16
- data/pg_engine/app/components/inline_edit/inline_edit_component.rb +1 -1
- data/pg_engine/app/decorators/pg_engine/base_record_decorator.rb +7 -0
- data/pg_engine/config/simple_form/simple_form_bootstrap.rb +16 -1
- data/pg_layout/app/javascript/application.js +23 -21
- data/pg_layout/app/javascript/controllers/pg_form_controller.js +15 -0
- data/pg_rails/lib/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91cd30e1ebe3fd2ec058f38ac2ad843421e8bb65c989aa5c8b5b7597703719f5
|
4
|
+
data.tar.gz: ceeaa8d7d5a2e3cfb32b39ff6c5da0b4c497a826685ef35f92be2cade7ad2d28
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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 &&
|
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
|
+
|
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
|
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
|
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
|
+
|
|
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, '
|
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
|
-
=
|
3
|
-
=
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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: :
|
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 =
|
10
|
-
Trix.config.lang.bold =
|
11
|
-
Trix.config.lang.bullets =
|
12
|
-
Trix.config.lang.byte =
|
13
|
-
Trix.config.lang.bytes =
|
14
|
-
Trix.config.lang.captionPlaceholder =
|
15
|
-
Trix.config.lang.code =
|
16
|
-
Trix.config.lang.heading1 =
|
17
|
-
Trix.config.lang.indent =
|
18
|
-
Trix.config.lang.italic =
|
19
|
-
Trix.config.lang.link =
|
20
|
-
Trix.config.lang.numbers =
|
21
|
-
Trix.config.lang.outdent =
|
22
|
-
Trix.config.lang.quote =
|
23
|
-
Trix.config.lang.redo =
|
24
|
-
Trix.config.lang.remove =
|
25
|
-
Trix.config.lang.strike =
|
26
|
-
Trix.config.lang.undo =
|
27
|
-
Trix.config.lang.unlink =
|
28
|
-
Trix.config.lang.url =
|
29
|
-
Trix.config.lang.urlPlaceholder =
|
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
|
}
|
data/pg_rails/lib/version.rb
CHANGED