base_editing_bootstrap 1.14.0 → 1.15.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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +14 -0
  4. data/app/controllers/base_editing_controller.rb +11 -0
  5. data/app/helpers/utilities/form_helper.rb +7 -3
  6. data/app/helpers/utilities/template_helper.rb +11 -3
  7. data/app/policies/base_model_policy.rb +21 -1
  8. data/app/views/base_editing/_form_field.html.erb +2 -3
  9. data/app/views/base_editing/_form_full_components.html.erb +2 -2
  10. data/app/views/base_editing/_nested_row_form_readonly.html.erb +8 -0
  11. data/app/views/base_editing/form_field/_accept_has_many_nested_field_readonly.html.erb +22 -0
  12. data/app/views/base_editing/form_field/_accept_has_one_nested_field_readonly.html.erb +4 -0
  13. data/app/views/base_editing/form_field/_base_readonly.html.erb +8 -0
  14. data/app/views/base_editing/form_field/_belongs_to_select.html.erb +2 -2
  15. data/app/views/base_editing/form_field/_belongs_to_select_readonly.html.erb +6 -0
  16. data/app/views/base_editing/form_field/_boolean.html.erb +1 -1
  17. data/app/views/base_editing/form_field/_boolean_readonly.html.erb +2 -0
  18. data/app/views/base_editing/form_field/_date_readonly.html.erb +2 -0
  19. data/app/views/base_editing/form_field/_datetime_readonly.html.erb +2 -0
  20. data/app/views/base_editing/form_field/_decimal_readonly.html.erb +2 -0
  21. data/app/views/base_editing/form_field/_enum_readonly.html.erb +2 -0
  22. data/app/views/base_editing/form_field/_has_one_attachment.html.erb +16 -12
  23. data/app/views/base_editing/form_field/_has_one_attachment_readonly.html.erb +12 -0
  24. data/app/views/base_editing/form_field/_integer_readonly.html.erb +2 -0
  25. data/app/views/base_editing/form_field/_textarea_readonly.html.erb +7 -0
  26. data/lib/base_editing_bootstrap/VERSION +1 -1
  27. data/lib/generators/base_editing_bootstrap/field_override/field_override_generator.rb +5 -2
  28. data/spec/support/external_shared/pundit.rb +1 -0
  29. metadata +15 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74db6610e2c8ab5c7f25de60eb6fb1c7ba1fa83570cd552a3356674356f02518
4
- data.tar.gz: 8aea6970cecd4fa8623711b21d9ec77e2b2657757dfa94c91e94028b687a074e
3
+ metadata.gz: d69ef1800e2eece675666b76837ae189f47c6f054031c12990a4b36181fca951
4
+ data.tar.gz: e345a8d8545068e50128afe6e55d212fe5f6e87555309898fb72ed0add5e0d69
5
5
  SHA512:
6
- metadata.gz: 5713323d93896548db8ee7fd75b187e5b7b6b61efb76c3855a92c79139eaa993af1a480a6cc1fe85c84a95e9b8af1f2c0dabe615ce14815728450bbd4390b10e
7
- data.tar.gz: 1a6068cc2a7b296c4f8d0a3a20097efd9dddb1752bb6e5e4844053ec8f6997eac49183af26d6873949c44d4bce05235ebfb655f171d7c0d2e203a48bef8988ae
6
+ metadata.gz: 37e059fd372aeb9ef27780523d13d336e4815c6afb8792990b6a375f1c60a1dfb951d48ea2231045a2715de8022138eb8732dfaa313b2e06d77ed23e1a4ee731
7
+ data.tar.gz: 4e8778eefe88514f17133dab5c96d5d8eaad61cb71bdf82b5ace11226af0f737a8e4ff15dd1609efd7555610aeaaec8e4783175103f4ad2e0323acd69ee6e2dd
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
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.15.0 - 2026-04-09
6
+ #### Features
7
+ - Add Read only mode (#25) - (0ba3da2) - Marino Bonetti
8
+
9
+ - - -
10
+
5
11
  ## 1.14.0 - 2026-03-19
6
12
  #### Features
7
13
  - Nested elements with limit from rails config (#24) - (f003ce4) - Marino Bonetti
data/README.md CHANGED
@@ -292,6 +292,20 @@ Note:
292
292
 
293
293
  Fai riferimento all'implementazione di esempio del dummy `Company->addresses`
294
294
 
295
+ ### ReadOnly
296
+ E' possibile renderizzare i campi di un modello in sola lettura, andando a ridefinire nella policy
297
+ il metodo `attribute_is_readonly(attribute_name)`.
298
+ Per ogni campo abbiamo la versione NOME_CAMPO_readonly.html.erb che viene renderizzato quando il metodo
299
+ precedente restituisce true.
300
+ I nested attributes verranno renderizzati rispetto a quanto definito dal
301
+ campo padre.
302
+ La ricerca dei partial avviene nella stessa modalità dei campi sopra definiti.
303
+ Al generator per i campi standard basta aggiungere il parametro `--readonly` per avere la versione NOME_CAMPO_readonly.html.erb:
304
+ ```shell
305
+ rails g base_editing_bootstrap:field_override ModelName field1 field2:type --readonly
306
+ ```
307
+
308
+
295
309
  ### Translations
296
310
 
297
311
  #### Index buttons:
@@ -5,6 +5,7 @@ class BaseEditingController < RestrictedAreaController
5
5
  :edit_custom_polymorphic_path,
6
6
  :form_attributes,
7
7
  :form_builder,
8
+ :readonly_attribute?,
8
9
  :index_custom_polymorphic_path,
9
10
  :new_custom_polymorphic_path,
10
11
  :show_custom_polymorphic_path
@@ -131,6 +132,16 @@ class BaseEditingController < RestrictedAreaController
131
132
  policy.public_send(method_name)
132
133
  end
133
134
 
135
+ def readonly_attribute?(attribute, model = base_class.new, action = override_pundit_action_name)
136
+ policy = policy(model)
137
+ method_name = if policy.respond_to?("attribute_is_readonly_for_#{action}")
138
+ "attribute_is_readonly_for_#{action}"
139
+ else
140
+ "attribute_is_readonly"
141
+ end
142
+ policy.public_send(method_name, attribute)
143
+ end
144
+
134
145
  def load_object
135
146
  @object = base_class.find(params[:id])
136
147
 
@@ -19,10 +19,13 @@ module Utilities
19
19
  #
20
20
  # @param [Forms::Base] form
21
21
  # @param [Symbol] field
22
- def form_print_field(form, field)
22
+ # @param [Boolean] readonly -> rende possibile nelle nested form, nel caso arrivi da un field padre che definisce
23
+ # il campo come readonly di non controllare nemmeno la policy(il padre ha priorità su figlio)
24
+ # @return [ActiveSupport::SafeBuffer]
25
+ def form_print_field(form, field, readonly: nil)
23
26
  locals = {form:, field:}
24
27
  if form.object.class.respond_to?(:field_to_form_partial) and (generic_field = form.object.class.field_to_form_partial(field))
25
- type= :custom
28
+ type = :custom
26
29
  elsif form.object.class.respond_to?(:defined_enums) && form.object.class.defined_enums.key?(field.to_s)
27
30
  type = :enum
28
31
  generic_field = "enum"
@@ -89,7 +92,8 @@ module Utilities
89
92
  form.object,
90
93
  field,
91
94
  "form_field",
92
- generic_field
95
+ generic_field,
96
+ readonly: (readonly.nil? ? readonly_attribute?(field, form.object) : readonly)
93
97
  )
94
98
  bs_logger.debug do
95
99
  <<~TEXT
@@ -12,7 +12,8 @@ module Utilities::TemplateHelper
12
12
  # @param [Symbol] field
13
13
  # @param [String] base_path
14
14
  # @param [String] generic_field
15
- def find_template_with_fallbacks(obj, field, base_path, generic_field)
15
+ # @param [Boolean] readonly #aggiunge nella ricerca del template la versione readonly
16
+ def find_template_with_fallbacks(obj, field, base_path, generic_field, readonly: false)
16
17
  # nei casi in cui passiamo la classe e non l'oggetto, dobbiamo utilizzare un metodo interno a rails per
17
18
  # avere la partial_path
18
19
 
@@ -31,7 +32,7 @@ module Utilities::TemplateHelper
31
32
  end
32
33
 
33
34
  bs_logger.tagged(field) do
34
- [
35
+ casistiche = [
35
36
  # Precedenza modello e campo specifico
36
37
  ["Campo SPECIFICO + inheritance tra modelli", field, obj_base_paths],
37
38
  # cerco tramite nome modello semplice, con namespace della risorsa (cell_field,header_field,form_field) e nome del campo specifico
@@ -42,7 +43,14 @@ module Utilities::TemplateHelper
42
43
  ["Campo GENERICO + inheritance controllers", "#{base_path}/#{generic_field}", lookup_context.prefixes],
43
44
  ["Campo GENERICO + inheritance tra modelli", generic_field, obj_base_paths],
44
45
  ["Default BaseEditingController", "base_editing/#{base_path}/#{generic_field}", []],
45
- ].each do |desc, partial, prefixes|
46
+ ]
47
+ # In caso di readonly andremo a ricercare solamente la versione di quel tipo
48
+ if readonly
49
+ casistiche = casistiche.collect do |desc, partial, prefixes|
50
+ [desc, "#{partial}_readonly", prefixes]
51
+ end
52
+ end
53
+ casistiche.each do |desc, partial, prefixes|
46
54
  bs_logger.debug { "#{desc} - partial:`#{partial}` in #{prefixes.inspect}" }
47
55
  if lookup_context.exists?(partial, prefixes, true)
48
56
  return lookup_context.find(partial, prefixes, true)
@@ -9,13 +9,33 @@ class BaseModelPolicy < ApplicationPolicy
9
9
 
10
10
  def show? = general_rule
11
11
 
12
- # Questo metodo può essere anche scritto specifico per azione:
12
+ # Questo metodo può essere richiamato specifico per azione:
13
13
  # - permitted_attributes_for_create
14
14
  # - permitted_attributes_for_update
15
+ # - permitted_attributes_for_ACTION_NAME
16
+ # Quindi nella policy possiamo differenziare le due situazioni
15
17
  def permitted_attributes = []
16
18
 
19
+ # Questo metodo può essere richiamato specifico per azione:
20
+ # - editable_attributes_for_create
21
+ # - editable_attributes_for_update
22
+ # - editable_attributes_for_ACTION_NAME
23
+ # Quindi nella policy possiamo differenziare le due situazioni
17
24
  def editable_attributes = []
18
25
 
26
+ ##
27
+ # Permette di specificare se un attributo è di sola lettura durante il rendering della form.
28
+ # Oltre alla versione standard è possibile definire il metodo specificando il tipo di azione con il
29
+ # medesimo formato utilizzato negli altri metodi:
30
+ # - attribute_is_readonly_for_create?
31
+ # - attribute_is_readonly_for_update?
32
+ # - attribute_is_readonly_for_ACTION_NAME?
33
+ #
34
+ # @param attribute [Symbol] nome dell'attributo
35
+ # @param action_name [String] nome dell'azione
36
+ # @return [Boolean] true se l'attributo è di sola lettura, false altrimenti
37
+ def attribute_is_readonly(_attribute) = false
38
+
19
39
  def permitted_attributes_for_ransack
20
40
  record.class.column_names + record.class._ransackers.keys
21
41
  end
@@ -4,11 +4,10 @@
4
4
  # - form -> FormBuilder
5
5
  # - form_field -> String
6
6
  %>
7
- <%# locals: (form:, form_field:) -%>
7
+ <%# locals: (form:, form_field:,readonly:nil) -%>
8
8
  <%
9
9
  input_group_classes = ["mb-1"]
10
-
11
- content = form_print_field(form, form_field)
10
+ content = form_print_field(form, form_field, readonly: readonly)
12
11
  unless content.match "checkbox"
13
12
  input_group_classes << "input-group"
14
13
  end
@@ -2,13 +2,13 @@
2
2
  Questo partial è il raggruppamento di tutti gli elementi tranne il footer del form.
3
3
  Serve per riutilizzarlo anche nel nested attributes come base per costruire tutti gli elementi
4
4
  %>
5
- <%# locals: (form:) -%>
5
+ <%# locals: (form:,readonly:nil) -%>
6
6
  <%= render layout: "form_body_container" do %>
7
7
  <%= render partial: "form_field_header", locals: {form:} %>
8
8
  <%= render partial: "form_base_errors", locals: {form:} if form.object.errors.key?(:base) %>
9
9
  <%= render layout: "form_fields_container" do %>
10
10
  <%= render collection: form_attributes(form.object),
11
11
  layout: "form_field_container",
12
- partial: "form_field", locals: {form:} %>
12
+ partial: "form_field", locals: {form:, readonly: readonly} %>
13
13
  <% end %>
14
14
  <% end %>
@@ -0,0 +1,8 @@
1
+ <tr id="<%= dom_id(form.object) %>">
2
+ <% policy(form.object).editable_attributes.each do |field| %>
3
+ <td>
4
+ <%= form_print_field(form, field, readonly: true) %>
5
+ <%= error_messages_for(form.object, field) %>
6
+ </td>
7
+ <% end %>
8
+ </tr>
@@ -0,0 +1,22 @@
1
+ <%# locals: (form:, field:,new_object:) -%>
2
+ <%= content_tag :table, class: "table read-only" do %>
3
+ <thead>
4
+ <tr>
5
+ <% policy(new_object).editable_attributes.each do |field| %>
6
+ <th>
7
+ <%= new_object.class.human_attribute_name(field) %>
8
+ </th>
9
+ <% end %>
10
+ </tr>
11
+ </thead>
12
+
13
+ <tbody>
14
+
15
+ <%= form.fields_for field do |form_for_sections| %>
16
+ <%= render "nested_row_form_readonly", form: form_for_sections %>
17
+ <% end %>
18
+
19
+ </tbody>
20
+
21
+ <% end %>
22
+
@@ -0,0 +1,4 @@
1
+ <%# locals: (form:, field:) -%>
2
+ <%= form.fields_for field do |form_for_sections| %>
3
+ <%= render partial: "form_full_components", locals: {form: form_for_sections, readonly: true} %>
4
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <%
2
+ ##
3
+ # Template per il rendering del vero campo input
4
+ # eseguire override nei casi in cui si voglia renderizzare qualcosa di differente
5
+ %>
6
+ <%# locals: (form:, field:) -%>
7
+ <%= form.text_field(field, readonly: true, disabled: true, name: "READONLY") %>
8
+
@@ -1,6 +1,6 @@
1
1
  <%# locals: (form:, field:,relation_class:,foreign_key:,value_method: :id, label_method: :option_label) -%>
2
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)),
3
+ value_method, label_method,
4
+ selected: form.object.send(foreign_key)),
5
5
  include_blank: true
6
6
  ) %>
@@ -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}, {disabled: true, readonly: true, name: "READONLY"}
6
+ ) %>
@@ -1,2 +1,2 @@
1
1
  <%# locals: (form:, field:) -%>
2
- <%= form.switch_box(field,label: field) %>
2
+ <%= form.switch_box(field, label: field) %>
@@ -0,0 +1,2 @@
1
+ <%# locals: (form:, field:) -%>
2
+ <%= form.switch_box(field, label: field, disabled: true, name: "READONLY") %>
@@ -0,0 +1,2 @@
1
+ <%# locals: (form:, field:) -%>
2
+ <%= form.date_field(field, disabled: true, readonly: true, name: "READONLY") %>
@@ -0,0 +1,2 @@
1
+ <%# locals: (form:, field:) -%>
2
+ <%= form.datetime_field(field, disabled: true, readonly: true, name: "READONLY") %>
@@ -0,0 +1,2 @@
1
+ <%# locals: (form:, field:, scale:2) -%>
2
+ <%= form.number_field(field, step: "0.#{"0" * (scale - 1)}1", disabled: true, readonly: true, name: "READONLY") %>
@@ -0,0 +1,2 @@
1
+ <%# locals: (form:, field:) -%>
2
+ <%= form.select(field, enum_collection(form.object.class, field, :form_field), {}, {disabled: true, readonly: true, name: "READONLY"}) %>
@@ -13,19 +13,23 @@
13
13
  JAVASCRIPT
14
14
 
15
15
  %>
16
- <%= form.hidden_field field, value: form.object.send(field).signed_id, id: hidden_field_id if is_attached %>
16
+ <div class="d-flex">
17
+ <%= form.hidden_field field, value: form.object.send(field).signed_id, id: hidden_field_id if is_attached %>
17
18
 
18
- <%= form.file_field field, direct_upload: true %>
19
+ <%= form.file_field field, direct_upload: true %>
19
20
 
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 %>
21
+ <% if is_attached %>
22
+
23
+ <%= content_tag :span, form.object.send(field).attachment.blob.filename, class: "input-group-text flex-grow-1", id: filename_id %>
24
+ <%= content_tag :button, icon(:trash),
25
+ onclick: javascript_clear_event,
26
+ class: "btn btn-outline-secondary rounded-0" %>
27
+ <%= link_to icon(:download), form.object.send(field), class: "btn btn-outline-secondary", target: :_blank %>
28
+
29
+ <% if form.object.send(field).representable? %>
30
+ <% content_for :form_field_ending, flush: true do %>
31
+ <%= content_tag :div, image_tag(form.object.send(field).representation(resize_to_limit: [100, 100])), id: preview_image_id %>
32
+ <% end %>
29
33
  <% end %>
30
34
  <% end %>
31
- <% end %>
35
+ </div>
@@ -0,0 +1,12 @@
1
+ <%# locals: (form:, field:) -%>
2
+ <% if form.object.send(field).attached? %>
3
+ <div class="d-flex">
4
+ <%= content_tag :span, form.object.send(field).attachment.blob.filename, class: "input-group-text flex-grow-1" %>
5
+ <%= link_to icon(:download), form.object.send(field), class: "btn btn-outline-secondary ms-1", target: :_blank %>
6
+ </div>
7
+ <% if form.object.send(field).representable? %>
8
+ <% content_for :form_field_ending, flush: true do %>
9
+ <%= content_tag :div, image_tag(form.object.send(field).representation(resize_to_limit: [100, 100])) %>
10
+ <% end %>
11
+ <% end %>
12
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <%# locals: (form:, field:) -%>
2
+ <%= form.number_field(field, step: "1", readonly: true) %>
@@ -0,0 +1,7 @@
1
+ <%
2
+ ##
3
+ # Template per il rendering del vero campo input
4
+ # eseguire override nei casi in cui si voglia renderizzare qualcosa di differente
5
+ %>
6
+ <%# locals: (form:, field:) -%>
7
+ <%= form.text_area(field, readonly: true) %>
@@ -1 +1 @@
1
- 1.14.0
1
+ 1.15.0
@@ -6,7 +6,8 @@ module BaseEditingBootstrap
6
6
  include BaseEditingBootstrap::GeneratorsHelpers
7
7
  source_root File.expand_path("../../../../app/views/base_editing", __dir__)
8
8
  argument :name, type: :string, banner: "Post", required: true
9
- argument :attributes, type: :array, default: [], banner: "field field:type"
9
+ argument :attributes, type: :array, default: [], banner: "field field[:type]"
10
+ class_option :readonly, type: :boolean, default: false, banner: "--readonly"
10
11
 
11
12
  TYPES = %i[base date datetime decimal integer enum boolean]
12
13
 
@@ -24,13 +25,15 @@ module BaseEditingBootstrap
24
25
 
25
26
  base_path = class_to_view_path(name)
26
27
 
28
+ readonly_suffix = options[:readonly] ? "_readonly" : ""
29
+
27
30
  attributes.each do |a|
28
31
  attr_name, type = a.split(":")
29
32
 
30
33
  type = :base if type.nil?
31
34
  type = type.to_sym
32
35
  raise "Type #{type} not found in #{TYPES}" unless TYPES.include?(type)
33
- copy_file "form_field/_#{type}.html.erb", File.join(*base_path,"form_field", "_#{attr_name}.html.erb")
36
+ copy_file "form_field/_#{type}#{readonly_suffix}.html.erb", File.join(*base_path,"form_field", "_#{attr_name}#{readonly_suffix}.html.erb")
34
37
  end
35
38
  end
36
39
 
@@ -28,6 +28,7 @@ RSpec.shared_examples "a standard base model policy" do |factory, check_default_
28
28
  [:permitted_scopes_for_ransack],
29
29
  [:editable_attributes],
30
30
  [:permitted_attributes],
31
+ [:attribute_is_readonly],
31
32
  ]
32
33
  end
33
34
 
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.14.0
4
+ version: 1.15.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: 2026-03-19 00:00:00.000000000 Z
11
+ date: 2026-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -353,6 +353,7 @@ files:
353
353
  - app/views/base_editing/_index_title_header.html.erb
354
354
  - app/views/base_editing/_navbar.html.erb
355
355
  - app/views/base_editing/_nested_row_form.html.erb
356
+ - app/views/base_editing/_nested_row_form_readonly.html.erb
356
357
  - app/views/base_editing/_new_page_title_header.html.erb
357
358
  - app/views/base_editing/_search.html.erb
358
359
  - app/views/base_editing/_search_field.erb
@@ -367,17 +368,29 @@ files:
367
368
  - app/views/base_editing/cell_field/_timestamps.html.erb
368
369
  - app/views/base_editing/edit.html.erb
369
370
  - app/views/base_editing/form_field/_accept_has_many_nested_field.html.erb
371
+ - app/views/base_editing/form_field/_accept_has_many_nested_field_readonly.html.erb
370
372
  - app/views/base_editing/form_field/_accept_has_one_nested_field.html.erb
373
+ - app/views/base_editing/form_field/_accept_has_one_nested_field_readonly.html.erb
371
374
  - app/views/base_editing/form_field/_base.html.erb
375
+ - app/views/base_editing/form_field/_base_readonly.html.erb
372
376
  - app/views/base_editing/form_field/_belongs_to_select.html.erb
377
+ - app/views/base_editing/form_field/_belongs_to_select_readonly.html.erb
373
378
  - app/views/base_editing/form_field/_boolean.html.erb
379
+ - app/views/base_editing/form_field/_boolean_readonly.html.erb
374
380
  - app/views/base_editing/form_field/_date.html.erb
381
+ - app/views/base_editing/form_field/_date_readonly.html.erb
375
382
  - app/views/base_editing/form_field/_datetime.html.erb
383
+ - app/views/base_editing/form_field/_datetime_readonly.html.erb
376
384
  - app/views/base_editing/form_field/_decimal.html.erb
385
+ - app/views/base_editing/form_field/_decimal_readonly.html.erb
377
386
  - app/views/base_editing/form_field/_enum.html.erb
387
+ - app/views/base_editing/form_field/_enum_readonly.html.erb
378
388
  - app/views/base_editing/form_field/_has_one_attachment.html.erb
389
+ - app/views/base_editing/form_field/_has_one_attachment_readonly.html.erb
379
390
  - app/views/base_editing/form_field/_integer.html.erb
391
+ - app/views/base_editing/form_field/_integer_readonly.html.erb
380
392
  - app/views/base_editing/form_field/_textarea.html.erb
393
+ - app/views/base_editing/form_field/_textarea_readonly.html.erb
381
394
  - app/views/base_editing/header_field/_base.html.erb
382
395
  - app/views/base_editing/index.html.erb
383
396
  - app/views/base_editing/new.html.erb