base_editing_bootstrap 1.3.2 → 1.5.0

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: 2e340e913487e9367deddd3f112c3a379af1ae132da18d27f19b44b6c4f133f6
4
- data.tar.gz: 35c0c82b8cc25665ddbeced4615baec2076ca3c6dc33651cc32d73b622d0b761
3
+ metadata.gz: e6bf71d45d64bd942a3891d528a28a6ef9b300c31e5764aa27a2c26bd58b64a8
4
+ data.tar.gz: f2d6638d9c2db49c57f91883a4be6dc7aa5e4232c64b4b98304c3233c61e02bb
5
5
  SHA512:
6
- metadata.gz: fca88f75c5a9e90adf8fc20a6cb46165745a90545649542f984b70b3dfb5b9310fbfaf11d9fc58debbde83022c46d8ab376b475ea64df88ac608f981e17fd567
7
- data.tar.gz: f7f4fe4e1755e174b980915ecd685754f68a9e5ea80cc258aa31c50325c16c709448992e2a3b28a64808d09ddbbff2d0a673e6446f9470b09409614f751921e2
6
+ metadata.gz: 0b552e2dbb6d71861e4a073ee49a11cdceb3612ced84b4320661583e6c468020c17b8392790b7e87dfd7f0e8b05f7c94e4565b18921a43d0763e68b34da960e1
7
+ data.tar.gz: 351b8dd26cbaa739e9010d9b24d2721e554b7fdd3f478c5e5bce75717097fcc5ae377b26fadcbfec25b6d5d57b614f5881918a5f6148462fa4deb6a8f32f5fd0
data/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
  All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.
3
3
 
4
4
  - - -
5
+ ## 1.5.0 - 2025-01-16
6
+ #### Documentation
7
+ - Update documentation - (3a29e34) - Marino Bonetti
8
+ #### Features
9
+ - Render enum in index - (c520cd1) - Marino Bonetti
10
+ - Belongs_to Form fields - (6572b9f) - Marino Bonetti
11
+ #### Refactoring
12
+ - Estrapolazione policy in metodo - (711746b) - Marino Bonetti
13
+
14
+ - - -
15
+
16
+ ## 1.4.0 - 2025-01-13
17
+ #### Bug Fixes
18
+ - Correct generator for values - (a83f07a) - Marino Bonetti
19
+ #### Features
20
+ - Has one attached automatic file_field - (fd32678) - Marino Bonetti
21
+
22
+ - - -
23
+
5
24
  ## 1.3.2 - 2025-01-10
6
25
  #### Bug Fixes
7
26
  - Fields in form inside layout - (a2e1d42) - Marino Bonetti
data/README.md CHANGED
@@ -25,6 +25,8 @@ Then run installer:
25
25
  $ bundle exec rails g base_editing_bootstrap:install
26
26
  ```
27
27
 
28
+ **Si presume quindi che ActiveStorage sia correttamente installato, completo del javascript per il direct upload**
29
+
28
30
  ### Generators
29
31
  Then Install dependency (if you run base_editing_bootstrap:install you are good to go):
30
32
  ```bash
@@ -143,7 +145,20 @@ Utilizzo per modello base, in questo esempio prendiamo come modello Post come es
143
145
  **Cell Field**:
144
146
  - created_at => timestamps.html.erb
145
147
  - updated_at => timestamps.html.erb
148
+ - Enum => _enum.html.erb
149
+ Per gli enum, le traduzioni dei labels di ogni valore provengono da i18n
150
+ attraverso l'helper: `Utilities::EnumHelper#enum_translation` con variant `:cell_field`
151
+ il quale sfrutta human_attribute_name del modello con 'attributo.enum_value',
152
+ quindi ad esempio per un modello `Post` con enum `categoria` e un enum `importante`, la ricerca nelle traduzioni
153
+ saranno così composte:
154
+ - it.activerecord.attributes.post/categoria.importante_cell_field
155
+ - it.activerecord.attributes.categoria.importante_cell_field
156
+ - it.attributes.importante_cell_field
157
+ - it.activerecord.attributes.post/categoria.importante
158
+ - it.activerecord.attributes.categoria.importante
159
+ - it.attributes.importante => nil
146
160
  - default => base.html.erb
161
+
147
162
  **Form Field**
148
163
  - Integer => _integer.html.erb
149
164
  - Float => _decimal.html.erb
@@ -152,9 +167,23 @@ Utilizzo per modello base, in questo esempio prendiamo come modello Post come es
152
167
  - Date => _date.html.erb
153
168
  - Boolean => _boolean.html.erb
154
169
  - Enum => _enum.html.erb
155
- Per gli enum, le traduzioni dei labels di ogni valore provvengono da i18n
156
- attraverso l'helper: `Utilities::EnumHelper#enum_translation`
157
- il quale utilizza il nome dell'attributo con
170
+ Per gli enum, le traduzioni dei labels di ogni valore provengono da i18n
171
+ attraverso l'helper: `Utilities::EnumHelper#enum_translation`" con variante `:form_field`
172
+ il quale sfrutta human_attribute_name del modello con 'attributo.enum_value',
173
+ quindi ad esempio per un modello `Post` con enum `categoria` e un enum `importante`, la ricerca nelle traduzioni
174
+ saranno così composte:
175
+ - it.activerecord.attributes.post/categoria.importante_form_field
176
+ - it.activerecord.attributes.categoria.importante_form_field
177
+ - it.attributes.importante_form_field
178
+ - it.activerecord.attributes.post/categoria.importante
179
+ - it.activerecord.attributes.categoria.importante
180
+ - it.attributes.importante => nil
181
+ - belongs_to => _belongs_to_select.html.erb
182
+ Come si può leggere dal partial, il modello che viene utilizzato come base dati per la collection deve
183
+ avere come metodo `option_label` che deve ritornare la label da utilizzare nelle options.
184
+ Di default questo metodo utilizza il semplice #to_s
185
+ Ha anche un metodo per il valore da utilizzare come chiave, di default viene dedotto dalla reflection
186
+ come anche il nome della classe da utilizzare come sorgente dei dati della collection
158
187
  - Default/String => _base.html.erb
159
188
 
160
189
  In futuro si prevede di aggiungere automatismi per renderizzare senza
@@ -2,6 +2,8 @@ module Utilities
2
2
  module FormHelper
3
3
  include TemplateHelper
4
4
  include EnumHelper
5
+ include IconHelper
6
+ include Pundit::Authorization
5
7
  ##
6
8
  # Metodo su cui eseguire override per i campi specifici rispetto all'oggetto gestito dal controller
7
9
  # @deprecated Utilizza form_print_field(form, field) senza sovrascriverlo
@@ -19,13 +21,28 @@ module Utilities
19
21
  def form_print_field(form, field)
20
22
  locals = {form:, field:}
21
23
  if form.object.class.respond_to?(:defined_enums) && form.object.class.defined_enums.key?(field.to_s)
24
+ type = :enum
22
25
  generic_field = "enum"
26
+ elsif form.object.class.respond_to?(:reflect_on_association) &&
27
+ form.object.class.reflect_on_association(field.to_s).is_a?(ActiveRecord::Reflection::BelongsToReflection)
28
+ # Abbiamo una relazione belongs_to da gestire
29
+ reflection = form.object.class.reflect_on_association(field.to_s)
30
+ type = :belongs_to
31
+ generic_field = "belongs_to_select"
32
+ locals[:relation_class] = reflection.klass
33
+ locals[:foreign_key] = reflection.foreign_key
23
34
  else
24
35
  if form.object.class.respond_to?(:type_for_attribute)
25
36
  type = form.object.class.type_for_attribute(field).type
37
+
38
+ # Se non abbiamo ancora il type tentiamo di capire se è di tipo attachment SINGOLO
39
+ if type.nil? and form.object.respond_to?(:"#{field}_attachment")
40
+ type = :has_one_attachment
41
+ end
26
42
  else
27
43
  type = :string
28
44
  end
45
+
29
46
  case type
30
47
  when :datetime
31
48
  generic_field = "datetime"
@@ -41,6 +58,8 @@ module Utilities
41
58
  generic_field = "integer"
42
59
  when :boolean
43
60
  generic_field = "boolean"
61
+ when :has_one_attachment
62
+ generic_field = "has_one_attachment"
44
63
  else
45
64
  generic_field = "base"
46
65
  end
@@ -3,6 +3,7 @@ module Utilities
3
3
  include TemplateHelper
4
4
  include PageHelper
5
5
  include IconHelper
6
+ include EnumHelper
6
7
 
7
8
  ##
8
9
  # Per aggiungere bottoni:
@@ -71,10 +72,16 @@ module Utilities
71
72
  when :created_at, :updated_at
72
73
  "timestamps"
73
74
  else
74
- type = klazz.type_for_attribute(field).type
75
+ if klazz.respond_to?(:defined_enums) && klazz.defined_enums.key?(field.to_s)
76
+ type = :enum
77
+ else
78
+ type = klazz.type_for_attribute(field).type
79
+ end
75
80
  case type
76
81
  when :boolean
77
82
  "boolean"
83
+ when :enum
84
+ "enum"
78
85
  else
79
86
  "base"
80
87
  end
@@ -30,3 +30,5 @@
30
30
  <%= error_messages_for(form.object, form_field) %>
31
31
  <% end %>
32
32
  <%= render partial: "editing_form_help_text", locals: {object: form.object, field: form_field} %>
33
+ <%= content_for :form_field_ending %>
34
+ <% content_for :form_field_ending, "", flush: true #RESET altrimenti ce lo troviamo nel successivo campo %>
@@ -0,0 +1,3 @@
1
+ <%# Renderizza il campo nella tabella della pagina dei risultati %>
2
+ <%# locals: (obj:,field:) -%>
3
+ <td><%= enum_translation(obj.class, field, obj.send(field), :cell_field) %></td>
@@ -0,0 +1,6 @@
1
+ <%# locals: (form:, field:,relation_class:,foreign_key:,value_method: :id, label_method: :option_label) -%>
2
+ <%= form.select(foreign_key, options_from_collection_for_select(policy_scope(relation_class),
3
+ value_method, label_method,
4
+ selected: form.object.send(foreign_key)),
5
+ include_blank: true
6
+ ) %>
@@ -1,2 +1,2 @@
1
1
  <%# locals: (form:, field:) -%>
2
- <%= form.select(field, enum_collection(form.object.class, field)) %>
2
+ <%= form.select(field, enum_collection(form.object.class, field, :form_field)) %>
@@ -0,0 +1,31 @@
1
+ <%# locals: (form:, field:) -%>
2
+ <%
3
+ is_attached = form.object.send(field).attached?
4
+ hidden_field_id = dom_id(form.object, "hidden_#{field}")
5
+ preview_image_id = dom_id(form.object, "preview_image_#{field}")
6
+ filename_id = dom_id(form.object, "filename_#{field}")
7
+
8
+ javascript_clear_event = <<~JAVASCRIPT
9
+ try{document.getElementById('#{hidden_field_id}').value = ''}catch{};
10
+ try{document.getElementById('#{preview_image_id}').remove()}catch{};
11
+ try{document.getElementById('#{filename_id}').remove()}catch{};
12
+ return false
13
+ JAVASCRIPT
14
+
15
+ %>
16
+ <%= form.hidden_field field, value: form.object.send(field).signed_id, id: hidden_field_id if is_attached %>
17
+
18
+ <%= form.file_field field, direct_upload: true %>
19
+
20
+ <% if is_attached %>
21
+ <%= content_tag :span, form.object.send(field).attachment.blob.filename, class: "input-group-text", id: filename_id %>
22
+ <%= content_tag :button, icon(:trash),
23
+ onclick: javascript_clear_event,
24
+ class: "btn btn-outline-secondary rounded-0" %>
25
+ <%= link_to icon(:download), form.object.send(field), class: "btn btn-outline-secondary", target: :_blank %>
26
+ <% if form.object.send(field).representable? %>
27
+ <% content_for :form_field_ending,flush:true do %>
28
+ <%= content_tag :div, image_tag(form.object.send(field).representation(resize_to_limit: [100, 100])), id: preview_image_id %>
29
+ <% end %>
30
+ <% end %>
31
+ <% end %>
@@ -43,7 +43,9 @@ Gem::Specification.new do |spec|
43
43
  spec.add_development_dependency 'faker', '~> 3.3'
44
44
  spec.add_development_dependency "puma", '~> 6.4'
45
45
  spec.add_development_dependency "sqlite3"
46
- spec.add_development_dependency "sprockets-rails", '~> 3.4'
46
+ spec.add_development_dependency "propshaft", '~> 1.1.0'
47
+ spec.add_development_dependency 'importmap-rails', '~> 2.1.0'
48
+ spec.add_development_dependency "image_processing", "~> 1.2"
47
49
  spec.add_development_dependency 'rails-i18n'
48
50
  spec.add_development_dependency "i18n-debug", '~> 1.2'
49
51
  spec.add_development_dependency "cssbundling-rails", '~> 1.4'
@@ -1 +1 @@
1
- 1.3.2
1
+ 1.5.0
@@ -8,6 +8,14 @@ module BaseEditingBootstrap
8
8
  include IsValidated
9
9
  include ActionTranslation
10
10
  delegate :ransackable_attributes, :ransackable_associations, to: :@class
11
+
12
+
13
+ ##
14
+ # Label da utilizzare nelle option per quando si genera le select dei belongs to
15
+ # @return [String,NilClass]
16
+ def option_label
17
+ to_s
18
+ end
11
19
  end
12
20
 
13
21
  class_methods do
@@ -37,21 +37,27 @@ module BaseEditingBootstrap::Searches
37
37
  end
38
38
 
39
39
  def search_fields
40
- Pundit.policy(@user, @model_klass).search_fields.collect { |f| Field.new(self, f) }
40
+ policy.search_fields.collect { |f| Field.new(self, f) }
41
41
  end
42
42
 
43
43
  def search_result_fields
44
- Pundit.policy(@user, @model_klass).search_result_fields
44
+ policy.search_result_fields
45
45
  end
46
46
 
47
47
  ##
48
48
  # Ritorna se il campo deve essere ordinabile o meno
49
49
  def sortable?(field)
50
- Pundit.policy(@user, @model_klass).sortable_search_result_fields.include?(field)
50
+ policy.sortable_search_result_fields.include?(field)
51
51
  end
52
52
 
53
53
  def persisted?
54
54
  false
55
55
  end
56
+
57
+ ##
58
+ # @return [ApplicationPolicy]
59
+ def policy
60
+ Pundit.policy(@user, @model_klass)
61
+ end
56
62
  end
57
63
  end
@@ -1,8 +1,8 @@
1
1
  class <%= class_name %>Policy < BaseModelPolicy
2
2
 
3
- def editable_attributes = %w[<%= attributes_names.join(" ") %>]
4
- def permitted_attributes = %w[<%= attributes_names.join(" ") %>]
5
- def search_result_fields = %w[<%= attributes_names.join(" ") %>]
3
+ def editable_attributes = %i[<%= attributes_names.join(" ") %>]
4
+ def permitted_attributes = %i[<%= attributes_names.join(" ") %>]
5
+ def search_result_fields = %i[<%= attributes_names.join(" ") %>]
6
6
  <%- if @search_attrs.any? -%>
7
7
  def search_fields
8
8
  %i[<%= @search_attrs.join(" ") %>]
@@ -11,7 +11,7 @@ class <%= class_name %>Policy < BaseModelPolicy
11
11
  <%- if @permitted_attributes.any? -%>
12
12
  # TODO check if correct with search_fields
13
13
  def permitted_attributes_for_ransack
14
- %w[<%= @permitted_attributes.join(" ") %>]
14
+ %i[<%= @permitted_attributes.join(" ") %>]
15
15
  end
16
16
  <%- end -%>
17
17
  end
@@ -1,4 +1,4 @@
1
- RSpec.shared_examples "a base model" do |ransack_permitted_attributes: [], ransack_permitted_associations: []|
1
+ RSpec.shared_examples "a base model" do |ransack_permitted_attributes: [], ransack_permitted_associations: [], option_label_method: :to_s|
2
2
 
3
3
  it_behaves_like "a validated? object"
4
4
 
@@ -6,6 +6,14 @@ RSpec.shared_examples "a base model" do |ransack_permitted_attributes: [], ransa
6
6
  expect(described_class).to respond_to(:human_action_message)
7
7
  end
8
8
 
9
+ it "have method for belongs_to options" do
10
+ instance = described_class.new
11
+ expect(instance).to respond_to(:option_label)
12
+
13
+ expect(instance).to receive(option_label_method).and_call_original
14
+ instance.option_label
15
+ end
16
+
9
17
  ##
10
18
  # Oggetto solitamente di classe User che identifichi l'utente a cui eseguire il check dei permessi
11
19
  let(:auth_object) { :auth_object }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: base_editing_bootstrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marino Bonetti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-10 00:00:00.000000000 Z
11
+ date: 2025-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -175,19 +175,47 @@ dependencies:
175
175
  - !ruby/object:Gem::Version
176
176
  version: '0'
177
177
  - !ruby/object:Gem::Dependency
178
- name: sprockets-rails
178
+ name: propshaft
179
179
  requirement: !ruby/object:Gem::Requirement
180
180
  requirements:
181
181
  - - "~>"
182
182
  - !ruby/object:Gem::Version
183
- version: '3.4'
183
+ version: 1.1.0
184
184
  type: :development
185
185
  prerelease: false
186
186
  version_requirements: !ruby/object:Gem::Requirement
187
187
  requirements:
188
188
  - - "~>"
189
189
  - !ruby/object:Gem::Version
190
- version: '3.4'
190
+ version: 1.1.0
191
+ - !ruby/object:Gem::Dependency
192
+ name: importmap-rails
193
+ requirement: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - "~>"
196
+ - !ruby/object:Gem::Version
197
+ version: 2.1.0
198
+ type: :development
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ requirements:
202
+ - - "~>"
203
+ - !ruby/object:Gem::Version
204
+ version: 2.1.0
205
+ - !ruby/object:Gem::Dependency
206
+ name: image_processing
207
+ requirement: !ruby/object:Gem::Requirement
208
+ requirements:
209
+ - - "~>"
210
+ - !ruby/object:Gem::Version
211
+ version: '1.2'
212
+ type: :development
213
+ prerelease: false
214
+ version_requirements: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - "~>"
217
+ - !ruby/object:Gem::Version
218
+ version: '1.2'
191
219
  - !ruby/object:Gem::Dependency
192
220
  name: rails-i18n
193
221
  requirement: !ruby/object:Gem::Requirement
@@ -335,14 +363,17 @@ files:
335
363
  - app/views/base_editing/_tabs.html.erb
336
364
  - app/views/base_editing/cell_field/_base.html.erb
337
365
  - app/views/base_editing/cell_field/_boolean.html.erb
366
+ - app/views/base_editing/cell_field/_enum.html.erb
338
367
  - app/views/base_editing/cell_field/_timestamps.html.erb
339
368
  - app/views/base_editing/edit.html.erb
340
369
  - app/views/base_editing/form_field/_base.html.erb
370
+ - app/views/base_editing/form_field/_belongs_to_select.html.erb
341
371
  - app/views/base_editing/form_field/_boolean.html.erb
342
372
  - app/views/base_editing/form_field/_date.html.erb
343
373
  - app/views/base_editing/form_field/_datetime.html.erb
344
374
  - app/views/base_editing/form_field/_decimal.html.erb
345
375
  - app/views/base_editing/form_field/_enum.html.erb
376
+ - app/views/base_editing/form_field/_has_one_attachment.html.erb
346
377
  - app/views/base_editing/form_field/_integer.html.erb
347
378
  - app/views/base_editing/header_field/_base.html.erb
348
379
  - app/views/base_editing/index.html.erb