lato_cms 3.0.9 → 3.0.10

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: a2f231b3624de0d429fc3f73d0e659d0556543c9a657d54b939308b581ad53b4
4
- data.tar.gz: be81b76ce28bc8b5e72345ac640eb4279285a9e70b9bf345f80399f7e4773cfb
3
+ metadata.gz: 67cc56a05385cb8ed79d06de5407bae73f23444f0872e02021696ebc1dd4000b
4
+ data.tar.gz: 794483334a4c7906ad00a370448ce488650bc6a94b6755a5f84bd2c909fd3676
5
5
  SHA512:
6
- metadata.gz: 28b6cc9fe5db40ff256bfed0055470a4c1d0ce1d22e9a601373832b6daac8b8215126555ab9e37d67ac58918e3b1d9c188cb0669716b7fb8370d8262b32c5276
7
- data.tar.gz: 7ec553cebf51a13d07823c77fbab3c06043365f30b14753ec86ff9d6847c386955d6536833b199754007e1f91073b0e353ef635e0eee7f87f19843e111ef410e
6
+ metadata.gz: d020a8b135ea587b61396ed1d8bc8314a9066a165d576e3a31aeb4c127894d0e0652729adf4c3c634a70ef07b075f54de1010d70dcff0ffbdb3f6218e3641fc7
7
+ data.tar.gz: 20a54bfd7811d1de1acfe2b44af5012fb5d1f810ab9fc2c84b037431e98b9f28541ae9c2a0dc17061db40670c72ce213670404e158ad40b991a35e2f6a534aec
@@ -1,9 +1,17 @@
1
1
  import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  export default class extends Controller {
4
- static targets = ['items', 'template', 'item', 'position', 'orderInput']
4
+ static targets = ['items', 'template', 'item', 'position', 'orderInput', 'addButton']
5
+ static values = { min: { type: Number, default: 0 }, max: { type: Number, default: 0 } }
6
+
7
+ connect () {
8
+ this.refresh()
9
+ }
5
10
 
6
11
  add () {
12
+ // Guard against exceeding max even if the button state is stale.
13
+ if (this.maxValue > 0 && this.itemTargets.length >= this.maxValue) return
14
+
7
15
  const itemId = window.crypto.randomUUID()
8
16
  const html = this.templateTarget.innerHTML
9
17
  .replaceAll('NEW_RECORD', itemId)
@@ -14,6 +22,9 @@ export default class extends Controller {
14
22
  }
15
23
 
16
24
  remove (event) {
25
+ // Block removal below the required minimum.
26
+ if (this.minValue > 0 && this.itemTargets.length <= this.minValue) return
27
+
17
28
  const item = event.currentTarget.closest('[data-lato-cms-repeater-target="item"]')
18
29
  if (!item) return
19
30
 
@@ -29,5 +40,22 @@ export default class extends Controller {
29
40
  const orderInput = item.querySelector('[data-lato-cms-repeater-target="orderInput"]')
30
41
  if (orderInput) orderInput.value = item.dataset.repeaterItemId
31
42
  })
43
+
44
+ this.updateControls()
45
+ }
46
+
47
+ // Toggle add/remove availability against the min/max constraints.
48
+ updateControls () {
49
+ const count = this.itemTargets.length
50
+
51
+ if (this.hasAddButtonTarget) {
52
+ this.addButtonTarget.disabled = this.maxValue > 0 && count >= this.maxValue
53
+ }
54
+
55
+ const disableRemove = this.minValue > 0 && count <= this.minValue
56
+ this.itemTargets.forEach((item) => {
57
+ const removeButton = item.querySelector('[data-action~="lato-cms-repeater#remove"]')
58
+ if (removeButton) removeButton.disabled = disableRemove
59
+ })
32
60
  }
33
61
  }
@@ -233,6 +233,19 @@ module LatoCms
233
233
  component_id = template_component[:component_id]
234
234
  item_ids = Array(repeater_order).reject(&:blank?).map(&:to_s)
235
235
 
236
+ # Enforce min/max item count (authoritative check). Missing settings = no constraint.
237
+ settings = template_component[:settings] || {}
238
+ min = settings['min'].presence && settings['min'].to_i
239
+ max = settings['max'].presence && settings['max'].to_i
240
+ if min && item_ids.size < min
241
+ errors << { field_id: template_component_id, errors: [t('lato_cms.repeater_min_error', count: min)] }
242
+ return
243
+ end
244
+ if max && item_ids.size > max
245
+ errors << { field_id: template_component_id, errors: [t('lato_cms.repeater_max_error', count: max)] }
246
+ return
247
+ end
248
+
236
249
  order_field = @page.fields.find_or_initialize_by(
237
250
  template_id: @page.template_id,
238
251
  template_component_id: template_component_id,
@@ -2,9 +2,14 @@
2
2
  <% saved_order = begin; order_field&.value.present? ? JSON.parse(order_field.value) : []; rescue JSON::ParserError; []; end %>
3
3
  <% fields_by_item = component_fields.reject(&:repeater_order?).group_by(&:repeater_item_id) %>
4
4
  <% item_ids = (saved_order.presence || fields_by_item.keys.compact) %>
5
- <% item_ids = [SecureRandom.uuid] if item_ids.blank? && tc[:settings]['min'].to_i.positive? %>
5
+ <% min = tc[:settings]['min'].to_i %>
6
+ <% max = tc[:settings]['max'].to_i %>
7
+ <%# Seed `min` empty items when the list is empty, so the minimum is met up front. %>
8
+ <% item_ids = Array.new(min) { SecureRandom.uuid } if item_ids.blank? && min.positive? %>
6
9
 
7
- <div data-controller="lato-cms-repeater">
10
+ <div data-controller="lato-cms-repeater"
11
+ data-lato-cms-repeater-min-value="<%= min %>"
12
+ data-lato-cms-repeater-max-value="<%= max %>">
8
13
  <div data-lato-cms-repeater-target="items">
9
14
  <% item_ids.each_with_index do |item_id, item_index| %>
10
15
  <% item_fields = (fields_by_item[item_id] || []).index_by(&:base_field_id) %>
@@ -16,7 +21,7 @@
16
21
  <%= render 'lato_cms/pages/repeater_item', tc: tc, item_id: 'NEW_RECORD', item_index: 'NEW_INDEX', item_fields: {} %>
17
22
  </template>
18
23
 
19
- <button type="button" class="btn btn-sm btn-outline-primary" data-action="lato-cms-repeater#add">
24
+ <button type="button" class="btn btn-sm btn-outline-primary" data-action="lato-cms-repeater#add" data-lato-cms-repeater-target="addButton">
20
25
  <i class="bi bi-plus-lg me-1"></i><%= t('lato_cms.repeater_add_item') %>
21
26
  </button>
22
27
  </div>
@@ -80,6 +80,8 @@ en:
80
80
  fields_save_component: Save
81
81
  repeater_add_item: Add item
82
82
  repeater_remove_item: Remove
83
+ repeater_min_error: "At least %{count} items are required"
84
+ repeater_max_error: "At most %{count} items are allowed"
83
85
  fields_component_missing_alert_html: "Component <strong>%{component_id}</strong> not found. The component configuration may have been removed."
84
86
  fields_previously_saved_data: "Previously saved data:"
85
87
  field_file_remove: Remove
@@ -80,6 +80,8 @@ it:
80
80
  fields_save_component: Salva
81
81
  repeater_add_item: Aggiungi elemento
82
82
  repeater_remove_item: Rimuovi
83
+ repeater_min_error: "Sono richiesti almeno %{count} elementi"
84
+ repeater_max_error: "Sono ammessi al massimo %{count} elementi"
83
85
  fields_component_missing_alert_html: "Componente <strong>%{component_id}</strong> non trovato. La configurazione del componente potrebbe essere stata rimossa."
84
86
  fields_previously_saved_data: "Dati salvati in precedenza:"
85
87
  field_file_remove: Rimuovi
@@ -1,3 +1,3 @@
1
1
  module LatoCms
2
- VERSION = "3.0.9"
2
+ VERSION = "3.0.10"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lato_cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.9
4
+ version: 3.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregorio Galante