pg_rails 7.0.8.pre.alpha → 7.0.8.pre.alpha.6

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -0
  3. data/pg_associable/app/assets/stylesheets/pg_associable.scss +39 -40
  4. data/pg_associable/app/helpers/pg_associable/form_builder_methods.rb +45 -1
  5. data/pg_associable/app/helpers/pg_associable/helpers.rb +6 -4
  6. data/pg_associable/app/javascript/asociable_controller.tsx +96 -20
  7. data/pg_associable/app/javascript/modal_controller.js +4 -95
  8. data/pg_associable/app/views/pg_associable/_resultados_inline.html.slim +6 -8
  9. data/pg_associable/app/views/pg_engine/base/_pg_associable_modal.html.slim +5 -32
  10. data/pg_engine/app/assets/stylesheets/pg_rails_b5.scss +49 -41
  11. data/pg_engine/app/controllers/pg_engine/resource_helper.rb +6 -2
  12. data/pg_engine/app/decorators/pg_engine/base_decorator.rb +2 -2
  13. data/pg_engine/app/helpers/pg_engine/flash_helper.rb +2 -2
  14. data/pg_engine/app/helpers/pg_engine/form_helper.rb +70 -0
  15. data/pg_engine/app/helpers/pg_engine/route_helper.rb +14 -6
  16. data/pg_engine/app/views/admin/accounts/_form.html.slim +1 -1
  17. data/pg_engine/app/views/admin/user_accounts/_form.html.slim +1 -1
  18. data/pg_engine/app/views/admin/users/_form.html.slim +1 -1
  19. data/pg_engine/app/views/pg_engine/base/index.html.slim +3 -3
  20. data/pg_engine/config/simple_form/simple_form_bootstrap.rb +17 -9
  21. data/pg_engine/db/migrate/20240222115722_create_active_storage_tables.active_storage.rb +57 -0
  22. data/pg_engine/lib/pg_engine/engine.rb +1 -1
  23. data/pg_engine/lib/pg_engine/route_helpers.rb +1 -0
  24. data/pg_engine/lib/pg_engine/utils/pdf_preview_generator.rb +50 -0
  25. data/pg_engine/lib/pg_engine.rb +3 -0
  26. data/pg_engine/spec/fixtures/test.pdf +0 -0
  27. data/pg_engine/spec/pg_engine/pdf_preview_generator_spec.rb +12 -0
  28. data/pg_layout/app/assets/stylesheets/sidebar.scss +10 -2
  29. data/pg_layout/app/javascript/nested_controller.js +48 -0
  30. data/pg_layout/app/javascript/pg_form_controller.js +13 -0
  31. data/pg_layout/app/javascript/utils.ts +34 -0
  32. data/pg_layout/app/views/layouts/pg_layout/devise.html.slim +1 -1
  33. data/pg_layout/app/views/layouts/pg_layout/layout.html.slim +14 -11
  34. data/pg_layout/app/views/pg_layout/_flash.html.slim +1 -1
  35. data/pg_layout/app/views/pg_layout/_navbar.html.erb +10 -0
  36. data/pg_layout/app/views/pg_layout/_sidebar.html.erb +3 -3
  37. data/pg_layout/index.js +4 -0
  38. data/pg_rails/lib/version.rb +1 -1
  39. data/pg_scaffold/lib/generators/pg_slim/templates/_form.html.slim +2 -2
  40. metadata +9 -3
  41. data/pg_associable/app/views/pg_associable/_resultados.html.slim +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a6d74fa06142003ba7e436907908f3f7ca491e8ab6367796424de5af92d19217
4
- data.tar.gz: a8a7545e0881a3fb79d3d2185314619341286488d7b1eeacb265c0adacb1b371
3
+ metadata.gz: 54b808ee15e453ddfc9031c04c599eea58099615a03b4d23abadec9ee3951d8c
4
+ data.tar.gz: 552aabdd132314da31928c4fcb2b59969ad7afe21c7a239f45fbc7738a1356ca
5
5
  SHA512:
6
- metadata.gz: 3f27603a1c050b0c5aada27652696a5b5cff62041d51b31ad99e4b09494a5b5f6b3f2376ce56bf725ae7bc7a3effcbb10d2851e5c9df7530902dec5a2d885f09
7
- data.tar.gz: ce9641619c78d375984b774fd007c7054e8ac6fe605d0f2c95c0f71bddfe498b081f64589c8a566a4da48d82f60b332d20f1359c937aa8cb34c137fa7a497014
6
+ metadata.gz: 5dddf3ab456741e7f671be016484caf643c1ad09a76ba96900707ab4e992049c5eb7da1273ab82b3fd83975278b72797cf4f9c0a178da5097f6343103e7968e7
7
+ data.tar.gz: 87c679f069138a579790599626636fcf31c44ea9a1393bd13314cb2c5268c6add6c46dc89eabcb742739a2d19179d0cf475860bdf108cd981e743183f0ae1a30
data/README.md CHANGED
@@ -86,3 +86,6 @@ be rails pg_engine_engine:install:migrations
86
86
  "build:css:prefix": "postcss ./pg_rails/builds/application.css --use=autoprefixer --output=./pg_rails/builds/application.css",
87
87
  "build:css": "yarn build:css:compile && yarn build:css:prefix",
88
88
 
89
+
90
+ ruby-vips
91
+ pdftoppm
@@ -1,44 +1,47 @@
1
1
  @use 'sass:color';
2
2
 
3
- [data-state=select-item] .show-on-new-item {
4
- display: none;
5
- }
6
- [data-state=new-item] .show-on-select-item {
7
- display: none;
8
- }
9
3
  .pg-form {
10
4
  .pg_associable {
11
5
  .limpiar {
12
6
  display: none;
13
7
  position: absolute;
14
- top: 8px;
15
- right: 10px;
8
+ right: 0.6em;
9
+ top: 0;
10
+ bottom: 0;
11
+
16
12
  i {
13
+ align-self: center;
17
14
  color: #6f7071;
18
15
  }
19
16
  }
20
17
  .pencil {
18
+ display: flex;
21
19
  position: absolute;
22
- top: 6px;
23
- right: 9px;
20
+ right: 0.6em;
21
+ top: 0;
22
+ bottom: 0;
24
23
  color: #6f7071;
25
24
  cursor: pointer;
26
25
  }
26
+ .pencil::before {
27
+ align-self: center;
28
+ }
27
29
  &.focus .pencil {
28
30
  display: none;
29
31
  }
30
32
  input[type=text] {
31
33
  background-color: white;
34
+ padding-right: 2em;
32
35
  }
33
36
  &.filled {
34
37
  .pencil {
35
38
  display: none;
36
39
  }
37
40
  .limpiar {
38
- display: inline-block;
41
+ display: flex;
39
42
  }
40
- input, input:focus {
41
- background-color: color.adjust(#a7b7bb, $saturation: +10%, $lightness: +20%);
43
+ .resultados-wrapper {
44
+ display:none!important;
42
45
  }
43
46
  }
44
47
  .resultados-wrapper {
@@ -46,11 +49,6 @@
46
49
  position: relative;
47
50
  }
48
51
  &:focus-within {
49
- .search-box {
50
- // outline: 1px solid color.adjust(#a7b7bb, $saturation: +30%);
51
- // border-radius: 3px;
52
- }
53
-
54
52
  &:has(.resultados) {
55
53
  input[type=text] {
56
54
  border-bottom-left-radius: 0!important;
@@ -64,36 +62,37 @@
64
62
  display: block;
65
63
  }
66
64
  }
67
- .resultados {
68
- position: absolute;
69
- // top: 30px;
70
- background-color: white;
71
- border: 1px solid #a7b7bb;
72
- border-top: none;
73
- border-radius: 4px;
74
- padding: 5px 11px;
75
- width: 100%;
76
-
77
- border-top-left-radius: 0;
78
- border-top-right-radius: 0;
79
- }
80
- }
81
- }
82
- .modal-asociable {
83
- .buscar input[type=text] {
84
- max-width: 180px;
85
- }
86
- .resultados {
87
- margin-top: 16px;
88
- border: 1px solid #c8c8c8;
89
65
  }
90
66
  }
67
+ // .modal-asociable {
68
+ // .buscar input[type=text] {
69
+ // max-width: 180px;
70
+ // }
71
+ // .resultados {
72
+ // margin-top: 16px;
73
+ // border: 1px solid #c8c8c8;
74
+ // }
75
+ // }
91
76
  .resultados {
92
77
  .list-group-item:hover {
93
78
  background-color: color.adjust(#a7b7bb, $saturation: +10%, $lightness: +20%);
94
79
  }
95
80
  }
81
+ .sub-wrapper {
82
+ overflow: auto;
83
+ box-shadow: 0px 9px 13px -3px rgba(0, 0, 0, 0.5);
84
+ // position: absolute;
85
+ // z-index: 1;
86
+ background-color: white;
87
+ border: 1px solid #a7b7bb;
88
+ border-top: none;
89
+ border-radius: 4px;
90
+ padding: 5px 11px;
91
+ width: 100%;
96
92
 
93
+ border-top-left-radius: 0;
94
+ border-top-right-radius: 0;
95
+ }
97
96
  .modal-asociable .modal-footer {
98
97
  justify-content: space-between;
99
98
  }
@@ -1,3 +1,4 @@
1
+ # TODO: mover a form_builder
1
2
  module PgAssociable
2
3
  module FormBuilderMethods
3
4
  def self.included(mod)
@@ -5,10 +6,53 @@ module PgAssociable
5
6
  mod.include PgEngine::RouteHelper
6
7
  end
7
8
 
9
+ MAXIMO_PARA_SELECT = 10
10
+ # TODO: si está entre 10 y 50, habilitar un buscador por js
11
+
8
12
  def pg_associable(atributo, options = {})
13
+ return input(atributo, options) if options[:disabled]
14
+
15
+ collection, puede_crear = collection_pc(atributo, options)
16
+ options.deep_merge!({ wrapper_html: { 'data-puede-crear': 'true' } }) if puede_crear
17
+
18
+ if !puede_crear && collection.count <= MAXIMO_PARA_SELECT
19
+ select_comun(atributo, options, collection)
20
+ else
21
+ select_pro(atributo, options, collection)
22
+ end
23
+ end
24
+
25
+ def collection_pc(atributo, _options)
26
+ klass = clase_asociacion(atributo)
27
+ user = template.controller.current_user
28
+ in_modal = options[:asociable].present?
29
+ puede_crear = !in_modal && Pundit::PolicyFinder.new(klass).policy.new(user, klass).new?
30
+ collection = Pundit::PolicyFinder.new(klass).scope.new(user, klass).resolve
31
+ [collection, puede_crear]
32
+ end
33
+
34
+ def select_pro(atributo, options, collection)
35
+ if (preload = options.delete(:preload))
36
+ collection = preload.is_a?(Integer) ? collection.limit(preload) : preload
37
+ options.deep_merge!({ wrapper_html: { 'data-preload': collection.decorate.to_json } })
38
+ end
39
+ # TODO: usar una clase más precisa para el modal?
40
+ options.deep_merge!({ wrapper_html: { data: { controller: 'asociable',
41
+ 'asociable-modal-outlet': '.modal' } } })
9
42
  options[:as] = 'pg_associable'
10
- options[:wrapper_html] = { data: { controller: 'asociable', 'asociable-modal-outlet': '.modal' } }
11
43
  association atributo, options
12
44
  end
45
+
46
+ def select_comun(atributo, options, collection)
47
+ options[:collection] = collection
48
+ association atributo, options
49
+ end
50
+
51
+ def clase_asociacion(atributo)
52
+ asociacion = object.class.reflect_on_all_associations.find { |a| a.name == atributo.to_sym }
53
+ nombre_clase = asociacion.options[:class_name]
54
+ nombre_clase = asociacion.name.to_s.camelize if nombre_clase.nil?
55
+ Object.const_get(nombre_clase)
56
+ end
13
57
  end
14
58
  end
@@ -1,5 +1,7 @@
1
1
  module PgAssociable
2
2
  module Helpers
3
+ MAX_RESULTS = 8
4
+
3
5
  def pg_respond_abrir_modal
4
6
  respond_to do |format|
5
7
  format.turbo_stream do
@@ -9,11 +11,11 @@ module PgAssociable
9
11
  end
10
12
 
11
13
  def pg_respond_buscar
12
- partial = params[:partial] || 'pg_associable/resultados'
13
- resultados = params[:resultados] || 'resultados'
14
- @collection = policy_scope(@clase_modelo).kept.query(params[:query]).limit(6)
14
+ partial = 'pg_associable/resultados_inline'
15
+ resultados_prefix = 'resultados-inline'
16
+ @collection = policy_scope(@clase_modelo).kept.query(params[:query]).limit(MAX_RESULTS)
15
17
  render turbo_stream:
16
- turbo_stream.update("#{resultados}-#{params[:id]}",
18
+ turbo_stream.update("#{resultados_prefix}-#{params[:id]}",
17
19
  partial:, locals: { collection: @collection })
18
20
  end
19
21
  end
@@ -6,13 +6,11 @@ export default class extends Controller {
6
6
  static outlets = ['modal']
7
7
 
8
8
  lastValue = null
9
- result = null
9
+ subWrapper = null
10
10
  elemId = null
11
11
  input = null
12
12
 
13
13
  connect () {
14
- console.log('connect asociable')
15
-
16
14
  // ID único para identificar el campo y el modal
17
15
  this.elemId = Math.trunc(Math.random() * 1000000000)
18
16
 
@@ -21,14 +19,22 @@ export default class extends Controller {
21
19
  this.element.setAttribute('data-asociable-modal-outlet', `.modal-${this.elemId}`)
22
20
  this.element.classList.add(`asociable-${this.elemId}`)
23
21
 
24
- this.result = document.createElement('div')
25
- this.result.setAttribute('id', `resultados-inline-${this.elemId}`)
26
- this.result.classList.add('resultados-wrapper')
27
- this.input.parentNode.appendChild(this.result)
22
+ const result = document.createElement('div')
23
+ result.classList.add('resultados-wrapper')
24
+ this.subWrapper = document.createElement('div')
25
+ this.subWrapper.setAttribute('id', `resultados-inline-${this.elemId}`)
26
+ this.subWrapper.classList.add('sub-wrapper')
27
+ this.subWrapper.classList.add('position-absolute')
28
+ this.subWrapper.classList.add('z-1')
29
+ result.appendChild(this.subWrapper)
30
+ this.input.parentNode.appendChild(result)
31
+
32
+ this.resetResultados()
28
33
 
29
34
  const input = this.element.querySelector('input[type=text]')
30
35
  if (input.value) {
31
36
  this.element.classList.add('filled')
37
+ input.setAttribute('readonly', 'true')
32
38
  }
33
39
  this.element.querySelector('.pencil').onclick = () => {
34
40
  input.focus()
@@ -55,6 +61,20 @@ export default class extends Controller {
55
61
  if (this.input.value.length === 0) {
56
62
  this.escribiAlgo()
57
63
  }
64
+
65
+ if (!this.element.closest('.modal')) {
66
+ const wHeight = window.visualViewport.height
67
+ const scrollTop = document.scrollingElement.scrollTop
68
+ const viewPortBottom = scrollTop + wHeight
69
+ const swHeight = parseInt(this.subWrapper.style.maxHeight) + 20
70
+ const elementTop = this.element.getBoundingClientRect().top + scrollTop
71
+ const inputBottom = this.input.getBoundingClientRect().bottom + scrollTop
72
+ const swBottom = inputBottom + swHeight
73
+
74
+ if (swBottom > viewPortBottom) {
75
+ document.scrollingElement.scroll({ top: elementTop })
76
+ }
77
+ }
58
78
  }
59
79
  this.input.onkeyup = (e) => {
60
80
  if (this.input.value.length === 0) {
@@ -72,6 +92,61 @@ export default class extends Controller {
72
92
  return false
73
93
  }
74
94
  }
95
+ this.setMaxHeight()
96
+ }
97
+
98
+ resetResultados () {
99
+ const rows = []
100
+ if (this.element.dataset.puedeCrear) {
101
+ rows.push(
102
+ <a key="new" href="javascript:void(0)"
103
+ className="list-group-item"
104
+ data-action="asociable#crearItem"
105
+ >
106
+ Nuevo
107
+ </a>
108
+ )
109
+ }
110
+ if (this.element.dataset.preload) {
111
+ JSON.parse(this.element.dataset.preload).forEach((object) => {
112
+ rows.push(
113
+ <a key={object.id} href="javascript:void(0)"
114
+ className="list-group-item"
115
+ data-action="asociable#selectItem"
116
+ data-id={object.id}
117
+ data-object={JSON.stringify(object)}
118
+ >
119
+ {object.to_s}
120
+ </a>
121
+ )
122
+ })
123
+ }
124
+ this.subWrapper.innerHTML = renderToStaticMarkup(
125
+ <div className="resultados" tabIndex={-1}>
126
+ <ul className="list-group list-group-flush">
127
+ {rows}
128
+ </ul>
129
+ </div>
130
+ )
131
+ }
132
+
133
+ setMaxHeight () {
134
+ let maxHeight
135
+ if (!this.element.closest('.modal')) {
136
+ const scrollTop = document.scrollingElement.scrollTop
137
+ const inputY = this.input.getBoundingClientRect().bottom + scrollTop
138
+ const bodyHeight = document.body.getBoundingClientRect().height
139
+ maxHeight = bodyHeight - inputY
140
+ if (maxHeight < 200) {
141
+ maxHeight = 200
142
+ }
143
+ if (bodyHeight < inputY + maxHeight) {
144
+ document.body.style.height = `${inputY + maxHeight}px`
145
+ }
146
+ } else {
147
+ maxHeight = 200
148
+ }
149
+ this.subWrapper.style.maxHeight = `${maxHeight - 20}px`
75
150
  }
76
151
 
77
152
  crearItem () {
@@ -82,7 +157,7 @@ export default class extends Controller {
82
157
  }
83
158
 
84
159
  const elem = (
85
- <form method="get" action={this.input.dataset.url_modal} data-turbo-stream="true">
160
+ <form method="get" action={this.input.dataset.urlModal} data-turbo-stream="true">
86
161
  <input type="hidden" name="id" value={this.elemId} />
87
162
  </form>
88
163
  )
@@ -98,7 +173,7 @@ export default class extends Controller {
98
173
  }
99
174
 
100
175
  buscando () {
101
- this.result.innerHTML = renderToStaticMarkup(
176
+ this.subWrapper.innerHTML = renderToStaticMarkup(
102
177
  <div className="resultados" tabIndex={-1}>
103
178
  <div className="fst-italic text-secondary">Buscando...</div>
104
179
  </div>
@@ -111,11 +186,14 @@ export default class extends Controller {
111
186
  } else {
112
187
  this.completarCampo(null)
113
188
  }
114
- this.result.innerHTML = ''
115
189
  }
116
190
 
117
191
  doSearch (force = false) {
192
+ if (this.element.classList.contains('filled')) {
193
+ return
194
+ }
118
195
  if (!force && this.input.value.length < 3) {
196
+ this.resetResultados()
119
197
  return
120
198
  }
121
199
  if (!force && this.input.value === this.lastValue) {
@@ -128,13 +206,13 @@ export default class extends Controller {
128
206
  }, 200)
129
207
  document.addEventListener('turbo:before-stream-render', function () {
130
208
  clearTimeout(timerId)
131
- })
209
+ // TODO: testear
210
+ }, { once: true })
132
211
  const elem = (
133
- <form method="post" action={this.input.dataset.url_search} data-turbo-stream="true">
212
+ <form method="post" action={this.input.dataset.urlSearch} data-turbo-stream="true">
134
213
  <input type="hidden" name="id" value={this.elemId} />
135
- <input type="hidden" name="partial" value="pg_associable/resultados_inline" />
136
- <input type="hidden" name="resultados" value="resultados-inline" />
137
214
  <input type="hidden" name="query" value={this.input.value} />
215
+ <input type="hidden" name="puede_crear" value={this.element.dataset.puedeCrear} />
138
216
  </form>
139
217
  )
140
218
  const form = document.createElement('div')
@@ -150,22 +228,20 @@ export default class extends Controller {
150
228
  if (object) {
151
229
  hiddenField.value = object.id
152
230
  textField.value = object.to_s
231
+ textField.setAttribute('readonly', 'true')
153
232
  this.element.classList.add('filled')
154
233
  this.element.dataset.object = object
155
234
  const event = new CustomEvent('pg_associable:changed', { detail: object })
156
235
  this.element.dispatchEvent(event)
157
236
  } else {
158
- textField.value = null
159
237
  hiddenField.value = null
238
+ textField.value = null
239
+ textField.removeAttribute('readonly')
160
240
  this.element.classList.remove('filled')
161
241
  this.element.dataset.object = null
162
242
  const event = new CustomEvent('pg_associable:changed')
163
243
  this.element.dispatchEvent(event)
164
244
  }
165
- this.result.innerHTML = ''
166
- }
167
-
168
- disconnect () {
169
- console.log('disconnect asociable')
245
+ this.resetResultados()
170
246
  }
171
247
  }
@@ -3,118 +3,27 @@ import * as bootstrap from 'bootstrap'
3
3
 
4
4
  export default class extends Controller {
5
5
  static outlets = ['asociable']
6
- static targets = ['response', 'result', 'searchInput', 'searchForm']
6
+ static targets = ['response']
7
7
 
8
8
  modalPuntero = null
9
- lastValue = ''
10
9
 
11
10
  connect (e) {
12
- console.log('ModalController connected')
13
- const modal = this.targets.element
14
- this.modalPuntero = new bootstrap.Modal(modal)
11
+ this.modalPuntero = new bootstrap.Modal(this.element)
15
12
  this.modalPuntero.show()
16
-
17
- if (this.searchInputTargets.length > 0) {
18
- this.bindSearchInput()
19
- }
20
- }
21
-
22
- debounce (callback, wait) {
23
- let timerId
24
- return (...args) => {
25
- clearTimeout(timerId)
26
- timerId = setTimeout(() => {
27
- callback(...args)
28
- }, wait)
29
- }
30
- }
31
-
32
- bindSearchInput () {
33
- const doSearchBounce = this.debounce((force) => {
34
- this.doSearch(force)
35
- }, 200)
36
- this.searchInputTarget.onkeydown = (e) => {
37
- if (e.keyCode === 13) {
38
- e.preventDefault()
39
- return false
40
- }
41
- }
42
- this.searchInputTarget.onkeyup = (e) => {
43
- if (e.keyCode === 13) {
44
- doSearchBounce(true)
45
- } else {
46
- doSearchBounce()
47
- }
48
- }
49
- }
50
-
51
- buscando () {
52
- this.resultTarget.innerHTML = `
53
- <ul class="resultados list-group list-group-flush" tabindex="-1">
54
- <li class="list-group-item">
55
- <span class="fst-italic text-secondary">Buscando...</span>
56
- </li>
57
- </ul>
58
- `
59
- }
60
-
61
- doSearch (force = false) {
62
- if (!force && this.searchInputTarget.value.length < 3) {
63
- return
64
- }
65
- if (!force && this.searchInputTarget.value === this.lastValue) {
66
- return
67
- }
68
- this.lastValue = this.searchInputTarget.value
69
-
70
- const timerId = setTimeout(() => {
71
- this.buscando()
72
- }, 200)
73
- document.addEventListener('turbo:before-stream-render', function (e) {
74
- clearTimeout(timerId)
75
- })
76
- this.searchFormTarget.requestSubmit()
77
- }
78
-
79
- selectItem (e) {
80
- const asociable = this.asociableOutlet
81
- if (e.target.dataset.object) {
82
- asociable.completarCampo(JSON.parse(e.target.dataset.object))
83
- } else {
84
- asociable.completarCampo(null)
85
- }
86
- this.remove()
87
13
  }
88
14
 
89
15
  responseTargetConnected (e) {
90
16
  const newObject = JSON.parse(e.dataset.response)
91
- const asociable = this.asociableOutlet
92
- asociable.completarCampo(newObject)
93
- this.remove()
94
- }
95
-
96
- remove () {
97
- this.targets.element.remove()
17
+ this.asociableOutlet.completarCampo(newObject)
18
+ this.element.remove()
98
19
  }
99
20
 
100
21
  openModal () {
101
22
  this.modalPuntero.show()
102
23
  }
103
24
 
104
- toggleCrearElegir (e) {
105
- const content = this.element.querySelector('.modal-content')
106
- const state = content.dataset.state
107
- const newValue = state === 'new-item' ? 'select-item' : 'new-item'
108
- content.setAttribute('data-state', newValue)
109
- }
110
-
111
25
  disconnect (e) {
112
- console.log('ModalController disconnected')
113
26
  this.modalPuntero.dispose()
114
27
  document.querySelectorAll('.modal-backdrop').forEach(e => { e.remove() })
115
28
  }
116
-
117
- buscar () {
118
- alert('buscar')
119
- }
120
29
  }
@@ -1,15 +1,13 @@
1
- .resultados tabindex="-1"
2
- - if collection.any?
3
- .list-group.list-group-flush
4
- = link_to 'Crear', 'javascript:void(0)',
1
+ .resultados.inline tabindex="-1"
2
+ ul.list-group.list-group-flush
3
+ - if params[:puede_crear].present?
4
+ = link_to 'Nuevo', 'javascript:void(0)',
5
5
  class: 'list-group-item', data: { action: 'asociable#crearItem' }
6
- = link_to 'Ninguno', 'javascript:void(0)',
7
- class: 'list-group-item', data: { action: 'asociable#selectItem' }
6
+ - if collection.any?
8
7
  - collection.each do |object|
9
8
  = link_to object.to_s, 'javascript:void(0)',
10
9
  class: 'list-group-item',
11
10
  data: { action: 'asociable#selectItem',
12
11
  id: object.id, object: object.decorate.to_json }
13
- - else
14
- ul.list-group.list-group-flush
12
+ - else
15
13
  li.list-group-item No hay resultados para "#{params[:query]}"
@@ -2,40 +2,13 @@
2
2
  tabindex="-1" data-controller="modal"
3
3
  data-modal-asociable-outlet=".asociable-#{params[:id]}"]
4
4
  .modal-dialog
5
- .modal-content.pg_associable data-state="select-item"
5
+ / TODO: pg_associable no va
6
+ .modal-content.pg_associable
6
7
  .modal-header
7
- .modal-title.show-on-new-item
8
+ .modal-title
9
+ / TODO: género "Nuevo/a"
8
10
  h3 Nuevo #{@clase_modelo.nombre_singular.downcase}
9
- .modal-title.show-on-select-item
10
- h3 Buscar #{@clase_modelo.nombre_singular.downcase}
11
11
  a.btn-close[type="button" data-bs-dismiss="modal" aria-label="Close"]
12
12
  .modal-body
13
- .show-on-select-item
14
- - if policy_scope(@clase_modelo).kept.count.zero?
15
- p No hay #{@clase_modelo.nombre_plural.downcase} aún
16
- = link_to "Crear el primer #{@clase_modelo.nombre_singular.downcase}",
17
- 'javascript:void(0)', data: { action: 'modal#toggleCrearElegir' }
18
- - else
19
- = form_tag namespaced_path(@clase_modelo, prefix: :buscar),
20
- data: { 'modal-target': 'searchForm' },
21
- method: :post, class: 'pg-form buscar' do
22
- = hidden_field_tag :id, params[:id]
23
- = text_field_tag :query, '', class: 'form-control',
24
- placeholder: 'Escribí algo para buscar',
25
- autocomplete: 'off',
26
- data: { 'modal-target': 'searchInput' }
27
- / = button_tag 'Buscar'
28
- .resultados-wrapper id="resultados-#{params[:id]}" data-modal-target="result"
29
- #pg-associable-form.show-on-new-item
13
+ .pg-associable-form
30
14
  = render partial: 'form', locals: { object: @clase_modelo.new, asociable: true }
31
-
32
- .modal-footer
33
- = link_to "Buscar #{@clase_modelo.nombre_singular.downcase} existente",
34
- 'javascript:void(0)', class: 'btn btn-primary show-on-new-item',
35
- data: { action: 'modal#toggleCrearElegir' }
36
- = link_to "Nuevo #{@clase_modelo.nombre_singular.downcase}",
37
- 'javascript:void(0)', class: 'btn btn-primary show-on-select-item',
38
- data: { action: 'modal#toggleCrearElegir' }
39
- = link_to "Sin #{@clase_modelo.nombre_singular.downcase}",
40
- 'javascript:void(0)', class: 'btn btn-secondary',
41
- data: { action: 'modal#selectItem' }