terrazzo 0.3.0 → 0.3.1

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: a9ba7563c1db759831717790db2c022eb3f2d343c3f393f6679e164c250f8fc5
4
- data.tar.gz: a985e9f57b97f224b26a58cd72d9e580666d0aae1b16efd8e722ce14460ad860
3
+ metadata.gz: f76fda78e25cb79116bd5f5f00b0b57e750503e3ebfdbee9a7bfe55dd8c17f34
4
+ data.tar.gz: 5cf113e4e1bfdd17591a3e50e1e993668da1408041efcc28a7f17b4a1b0eac05
5
5
  SHA512:
6
- metadata.gz: 877fed40c106cc9ed5443197322033abd8c4d51c5fa69cb596d63ca77b355ffeb4c3235a13125a6bb6c7f1f28a747cab2c2674ebf08fee6bb4a2c7f225fc1eed
7
- data.tar.gz: 24cdb50150d40149fda75e5fe376978222ab3b200247a006989cb52e98ea2e9482747ab49b3880f7557cb072ca089691f7468f3573a778eaec764bcf45b6cf3c
6
+ metadata.gz: b60b58629158604c651402f6f920372f07146115b05f46613a2909be8af868f17005092bf7c84e288a4789724408e59150801fdc0b4f59c6575db1e05bb60f37
7
+ data.tar.gz: 9f6342b35c22e98a56f465221ef5e0bcc8911fcf75ee33ebea146144232e84a85b3c199b4ae14ce5969868c983587ca2cb59660ba96e2d2123c9ee1cc71aec36
@@ -16,7 +16,7 @@ module Terrazzo
16
16
 
17
17
  prepend Terrazzo::UsesSuperglue::TemplateLookupOverride
18
18
 
19
- helper_method :namespace, :dashboard, :resource_name, :resource_class, :application_title, :terrazzo_page_identifier
19
+ helper_method :namespace, :dashboard, :resource_name, :resource_class, :application_title, :terrazzo_page_identifier, :route_exists?
20
20
 
21
21
  def index
22
22
  search = Terrazzo::Search.new(scoped_resource, dashboard, params[:search])
@@ -207,6 +207,16 @@ module Terrazzo
207
207
  "#{ns}/application/#{mapped_action}"
208
208
  end
209
209
 
210
+ def route_exists?(action)
211
+ @_route_exists_cache ||= {}
212
+ return @_route_exists_cache[action] if @_route_exists_cache.key?(action)
213
+
214
+ @_route_exists_cache[action] = Rails.application.routes.routes.any? do |route|
215
+ route.defaults[:controller] == controller_path &&
216
+ route.defaults[:action] == action.to_s
217
+ end
218
+ end
219
+
210
220
  private
211
221
 
212
222
  def resolver
@@ -5,7 +5,8 @@ json.pageTitle t("terrazzo.actions.edit", resource_name: resource_name)
5
5
  json.form do
6
6
  json.props({
7
7
  action: polymorphic_path([namespace, @resource]),
8
- method: "post"
8
+ method: "post",
9
+ encType: "multipart/form-data"
9
10
  })
10
11
  json.extras do
11
12
  if protect_against_forgery?
@@ -33,8 +33,8 @@ json.table do
33
33
  json.array! @resources do |resource|
34
34
  json.id resource.id
35
35
  json.showPath polymorphic_path([namespace, resource]) rescue nil
36
- json.editPath edit_polymorphic_path([namespace, resource]) rescue nil
37
- json.deletePath polymorphic_path([namespace, resource]) rescue nil
36
+ json.editPath route_exists?(:edit) ? (edit_polymorphic_path([namespace, resource]) rescue nil) : nil
37
+ json.deletePath route_exists?(:destroy) ? (polymorphic_path([namespace, resource]) rescue nil) : nil
38
38
 
39
39
  json.cells do
40
40
  json.array! @page.attribute_names do |attr|
@@ -89,4 +89,4 @@ end
89
89
 
90
90
  json.resourceName resource_name.pluralize
91
91
  json.singularResourceName resource_name
92
- json.newResourcePath new_polymorphic_path([namespace, resource_class]) rescue nil
92
+ json.newResourcePath route_exists?(:new) ? (new_polymorphic_path([namespace, resource_class]) rescue nil) : nil
@@ -6,7 +6,8 @@ json.pageTitle t("terrazzo.actions.new", resource_name: resource_name)
6
6
  json.form do
7
7
  json.props({
8
8
  action: polymorphic_path([namespace, resource_class]),
9
- method: "post"
9
+ method: "post",
10
+ encType: "multipart/form-data"
10
11
  })
11
12
  json.extras do
12
13
  if protect_against_forgery?
@@ -34,8 +34,8 @@ json.attributes do
34
34
  end
35
35
  end
36
36
 
37
- json.editPath edit_polymorphic_path([namespace, @resource]) rescue nil
38
- json.deletePath polymorphic_path([namespace, @resource]) rescue nil
37
+ json.editPath route_exists?(:edit) ? (edit_polymorphic_path([namespace, @resource]) rescue nil) : nil
38
+ json.deletePath route_exists?(:destroy) ? (polymorphic_path([namespace, @resource]) rescue nil) : nil
39
39
  json.indexPath begin
40
40
  url_for(controller: controller_path, action: :index, only_path: true)
41
41
  rescue ActionController::UrlGenerationError
@@ -71,8 +71,18 @@ module Terrazzo
71
71
  types[col.name.to_sym] = column_to_field_type(col)
72
72
  end
73
73
 
74
+ # Active Storage attachment names (used to filter internal associations)
75
+ attachment_names = if model_class.respond_to?(:reflect_on_all_attachments)
76
+ model_class.reflect_on_all_attachments.map(&:name).to_set
77
+ else
78
+ Set.new
79
+ end
80
+
74
81
  # Associations
75
82
  associations.each do |assoc|
83
+ # Skip Active Storage internal associations (e.g., document_attachment, document_blob)
84
+ next if active_storage_internal?(assoc.name, attachment_names)
85
+
76
86
  case assoc.macro
77
87
  when :belongs_to
78
88
  types[assoc.name] = assoc.options[:polymorphic] ? "Field::Polymorphic" : "Field::BelongsTo"
@@ -83,6 +93,13 @@ module Terrazzo
83
93
  end
84
94
  end
85
95
 
96
+ # Active Storage attachments
97
+ attachment_names.each do |name|
98
+ attachment = model_class.reflect_on_attachment(name)
99
+ next if attachment.macro == :has_many_attached
100
+ types[name] = "Field::Asset"
101
+ end
102
+
86
103
  types
87
104
  end
88
105
 
@@ -106,6 +123,15 @@ module Terrazzo
106
123
  end
107
124
  end
108
125
 
126
+ def active_storage_internal?(assoc_name, attachment_names)
127
+ name = assoc_name.to_s
128
+ attachment_names.any? do |att|
129
+ att_s = att.to_s
130
+ name == "#{att_s}_attachment" || name == "#{att_s}_blob" ||
131
+ name == "#{att_s}_attachments" || name == "#{att_s}_blobs"
132
+ end
133
+ end
134
+
109
135
  def has_enum?(column_name)
110
136
  model_class.defined_enums.key?(column_name.to_s)
111
137
  end
@@ -64,10 +64,13 @@ module Terrazzo
64
64
 
65
65
  def collection_includes
66
66
  collection_attr_set = Set.new(collection_attributes)
67
+ model = self.class.model
67
68
  attribute_types.each_with_object([]) do |(attr, type), includes|
68
69
  next unless collection_attr_set.include?(attr)
69
70
  next unless type.eager_load?
70
- next unless self.class.model.reflect_on_association(attr)
71
+ has_association = model.reflect_on_association(attr)
72
+ has_attachment = model.respond_to?(:reflect_on_attachment) && model.reflect_on_attachment(attr)
73
+ next unless has_association || has_attachment
71
74
  includes << attr
72
75
  end
73
76
  end
@@ -0,0 +1,34 @@
1
+ module Terrazzo
2
+ module Field
3
+ class Asset < Base
4
+ def serialize_value(mode)
5
+ return nil if data.nil? || !data.attached?
6
+
7
+ case mode
8
+ when :index
9
+ data.filename.to_s
10
+ when :show
11
+ { filename: data.filename.to_s, byteSize: data.byte_size, contentType: data.content_type }
12
+ when :form
13
+ { filename: data.filename.to_s, signedId: data.signed_id }
14
+ else
15
+ data.filename.to_s
16
+ end
17
+ end
18
+
19
+ class << self
20
+ def searchable?
21
+ false
22
+ end
23
+
24
+ def sortable?
25
+ false
26
+ end
27
+
28
+ def eager_load?
29
+ true
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -3,7 +3,8 @@ module Terrazzo
3
3
  class Date < Base
4
4
  def serialize_value(_mode)
5
5
  return nil if data.nil?
6
- data.to_s
6
+ format = options[:format]
7
+ format ? data.strftime(format) : data.to_s
7
8
  end
8
9
  end
9
10
  end
@@ -3,7 +3,8 @@ module Terrazzo
3
3
  class DateTime < Base
4
4
  def serialize_value(_mode)
5
5
  return nil if data.nil?
6
- data.iso8601
6
+ format = options[:format]
7
+ format ? data.strftime(format) : data.iso8601
7
8
  end
8
9
  end
9
10
  end
@@ -6,7 +6,10 @@ module Terrazzo
6
6
 
7
7
  case mode
8
8
  when :index
9
- data.size
9
+ count = data.size
10
+ label = attribute.to_s.humanize.downcase
11
+ label = label.singularize if count == 1
12
+ { count: count, label: label }
10
13
  when :form
11
14
  data.map { |r| r.id.to_s }
12
15
  when :show
@@ -1,8 +1,10 @@
1
1
  module Terrazzo
2
2
  module Field
3
3
  class Number < Base
4
- def serialize_value(_mode)
5
- data
4
+ def serialize_value(mode)
5
+ return data if data.nil? || mode == :form || !options.key?(:multiplier)
6
+
7
+ data * options[:multiplier]
6
8
  end
7
9
 
8
10
  def serializable_options
@@ -3,7 +3,8 @@ module Terrazzo
3
3
  class Time < Base
4
4
  def serialize_value(_mode)
5
5
  return nil if data.nil?
6
- data.to_s
6
+ format = options[:format]
7
+ format ? data.strftime(format) : data.to_s
7
8
  end
8
9
  end
9
10
  end
@@ -1,3 +1,3 @@
1
1
  module Terrazzo
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
data/lib/terrazzo.rb CHANGED
@@ -37,6 +37,7 @@ module Terrazzo
37
37
  autoload :HasMany, "terrazzo/field/has_many"
38
38
  autoload :HasOne, "terrazzo/field/has_one"
39
39
  autoload :Polymorphic, "terrazzo/field/polymorphic"
40
+ autoload :Asset, "terrazzo/field/asset"
40
41
  end
41
42
 
42
43
  module Page
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terrazzo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Terrazzo Contributors
@@ -242,6 +242,7 @@ files:
242
242
  - lib/terrazzo.rb
243
243
  - lib/terrazzo/base_dashboard.rb
244
244
  - lib/terrazzo/engine.rb
245
+ - lib/terrazzo/field/asset.rb
245
246
  - lib/terrazzo/field/associative.rb
246
247
  - lib/terrazzo/field/base.rb
247
248
  - lib/terrazzo/field/belongs_to.rb