glib-web 8.0.0 → 8.1.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 +4 -4
- data/app/helpers/glib/json_ui/view_builder/panels.rb +1 -0
- data/app/models/concerns/glib/enum_symbolization.rb +41 -4
- data/app/views/json_ui/garage/panels/carousel.json.jbuilder +7 -0
- data/app/views/json_ui/garage/test_page/logics_set.json.jbuilder +35 -0
- data/app/views/json_ui/garage/test_page/panels_association.json.jbuilder +42 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 22842c76cc4c92471f28991ff906491e61429a891a9da912aff82af48ac90125
|
|
4
|
+
data.tar.gz: dcb1bfce2a976cae302dc39662c3d696a9c951eb0934fdf6e7d0d2257d5ad48e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b094093515f7d56a0d4374779dac06b97ef70ee2bd164507668d03c22e5791913264ed68d3ea1ccf33aeeb7ae36cca6b939f78729c2ca94c228007d97024522f
|
|
7
|
+
data.tar.gz: 86a7cc0bc03aeefd9d96d3cbc06e382e0a9b1b6cb851a4b723dc701b825f474d5aac822151505932e320a166299bc246c722dbd9b5e34685b093bfc6826f1e54
|
|
@@ -31,9 +31,26 @@ module Glib
|
|
|
31
31
|
# key and is almost always a bug) and override the reader to return a symbol,
|
|
32
32
|
# so callers can compare with `record.status == :active` without tracking
|
|
33
33
|
# which form they're holding (see backend/01a_defensive_programming.md item 7).
|
|
34
|
+
#
|
|
35
|
+
# The same symbolization covers the per-attribute dirty-tracking readers
|
|
36
|
+
# (`status_was`, `status_in_database`, `status_change`, `saved_change_to_status`,
|
|
37
|
+
# ...), which Rails builds from the raw attribute rather than through the
|
|
38
|
+
# reader and would otherwise hand back the enum's string label. The dirty
|
|
39
|
+
# PREDICATES (`status_changed?(from: :draft)`) need no override: Rails casts
|
|
40
|
+
# their from:/to: through the enum type, so symbols already work there.
|
|
41
|
+
# Hash-form readers (`changes`, `saved_changes`, `attributes`) are left as
|
|
42
|
+
# Rails returns them: they are keyed by attribute name rather than written
|
|
43
|
+
# per attribute, and their consumers (serialization, audit trails, update
|
|
44
|
+
# payloads) expect Rails' native form.
|
|
34
45
|
module EnumSymbolization
|
|
35
46
|
extend ActiveSupport::Concern
|
|
36
47
|
|
|
48
|
+
# Per-attribute dirty readers returning the single value (string or nil).
|
|
49
|
+
VALUE_SUFFIXES = %w[_was _previously_was _before_last_save _in_database].freeze
|
|
50
|
+
# Per-attribute dirty readers returning a [before, after] pair, or nil when
|
|
51
|
+
# unchanged. `saved_change_to_<attr>` is the prefixed member of this set.
|
|
52
|
+
PAIR_SUFFIXES = %w[_change _previous_change _change_to_be_saved].freeze
|
|
53
|
+
|
|
37
54
|
class_methods do
|
|
38
55
|
def enum_symbolize(*attrs, **opts)
|
|
39
56
|
if attrs.size >= 2 && (attrs[1].is_a?(Hash) || attrs[1].is_a?(Array))
|
|
@@ -48,7 +65,7 @@ module Glib
|
|
|
48
65
|
# remove or move below `enum`.
|
|
49
66
|
attribute name, Glib::EnumSymbolization.backing_type(values)
|
|
50
67
|
enum name, values, **opts
|
|
51
|
-
|
|
68
|
+
glib_symbolize_enum(name)
|
|
52
69
|
else
|
|
53
70
|
# Legacy form: enum_symbolize :a[, :b, ...] for enums already declared.
|
|
54
71
|
if opts.any?
|
|
@@ -56,18 +73,38 @@ module Glib
|
|
|
56
73
|
"enum_symbolize: pass enum values as a braced hash, " \
|
|
57
74
|
"e.g. enum_symbolize :#{attrs.first}, { ... }"
|
|
58
75
|
end
|
|
59
|
-
attrs.each { |attr|
|
|
76
|
+
attrs.each { |attr| glib_symbolize_enum(attr) }
|
|
60
77
|
end
|
|
61
78
|
end
|
|
62
79
|
|
|
63
80
|
private
|
|
64
81
|
|
|
65
|
-
|
|
82
|
+
# Overrides are defined on the model class itself, above the generated
|
|
83
|
+
# attribute-methods module Rails includes, so each `super()` reaches the
|
|
84
|
+
# Rails implementation.
|
|
85
|
+
def glib_symbolize_enum(attr)
|
|
66
86
|
validates attr, presence: true
|
|
67
|
-
define_method(attr) { super()
|
|
87
|
+
define_method(attr) { Glib::EnumSymbolization.symbolize(super()) }
|
|
88
|
+
|
|
89
|
+
VALUE_SUFFIXES.each do |suffix|
|
|
90
|
+
define_method("#{attr}#{suffix}") { Glib::EnumSymbolization.symbolize(super()) }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
pair_methods = PAIR_SUFFIXES.map { |suffix| "#{attr}#{suffix}" } + ["saved_change_to_#{attr}"]
|
|
94
|
+
pair_methods.each do |method_name|
|
|
95
|
+
define_method(method_name) { super()&.map { |value| Glib::EnumSymbolization.symbolize(value) } }
|
|
96
|
+
end
|
|
68
97
|
end
|
|
69
98
|
end
|
|
70
99
|
|
|
100
|
+
# A label becomes a symbol; nil stays nil. Anything else passes through:
|
|
101
|
+
# with `validate: true` Rails casts an unknown raw value (99) to itself
|
|
102
|
+
# instead of raising, and that value must survive to fail validation
|
|
103
|
+
# rather than blow up in `to_sym`.
|
|
104
|
+
def self.symbolize(value)
|
|
105
|
+
value.is_a?(String) ? value.to_sym : value
|
|
106
|
+
end
|
|
107
|
+
|
|
71
108
|
# Infer the attribute type backing an enum from its declared values, so the
|
|
72
109
|
# type never depends on the (possibly not-yet-migrated) DB column. A hash
|
|
73
110
|
# whose values are strings backs a :string column; integer-keyed hashes and
|
|
@@ -34,5 +34,12 @@ json_ui_page json do |page|
|
|
|
34
34
|
panel.image height: height, url: image_url2
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
|
+
|
|
38
|
+
scroll.spacer height: 20
|
|
39
|
+
scroll.h1 text: 'Carousel with cycle'
|
|
40
|
+
scroll.panels_carousel width: 'matchParent', interval: 3000, childViews: ->(carousel) do
|
|
41
|
+
carousel.image url: image_url1, width: 'matchParent'
|
|
42
|
+
carousel.image url: image_url2, width: 'matchParent'
|
|
43
|
+
end
|
|
37
44
|
end
|
|
38
45
|
end
|
|
@@ -153,6 +153,41 @@ page.form(
|
|
|
153
153
|
res.fields_check name: 'user[tags][]', checkValue: 'b', label: 'Tag B', onChange: set_eq_check
|
|
154
154
|
res.spacer height: 8
|
|
155
155
|
res.label id: 'set_eq_status', text: 'PENDING'
|
|
156
|
+
|
|
157
|
+
res.spacer height: 16
|
|
158
|
+
res.h2 text: 'Logics Set - time of day'
|
|
159
|
+
res.spacer height: 8
|
|
160
|
+
# `minutesOfDay` parses a typed time of day exactly as a consuming
|
|
161
|
+
# app's server does and `formatHm` renders the length in explicit
|
|
162
|
+
# units ("4h", "1h 5m"), so a Start/End pair
|
|
163
|
+
# shows its duration live. The `+ 1440` before the `% 1440` keeps
|
|
164
|
+
# json-logic's JS remainder positive when the End is before the
|
|
165
|
+
# Start, which is also when "(next day)" is said. A missing time
|
|
166
|
+
# says a non-breaking space, not an empty string, so the label keeps
|
|
167
|
+
# its height and the page never jumps mid-typing.
|
|
168
|
+
duration_update = ->(action) do
|
|
169
|
+
start_minutes = { 'minutesOfDay' => { 'var' => 'user[start_time]' } }
|
|
170
|
+
end_minutes = { 'minutesOfDay' => { 'var' => 'user[end_time]' } }
|
|
171
|
+
action.logics_set(
|
|
172
|
+
targetId: 'duration_label',
|
|
173
|
+
conditionalData: {
|
|
174
|
+
text: {
|
|
175
|
+
'if' => [
|
|
176
|
+
{ 'or' => [{ '==' => [start_minutes, nil] }, { '==' => [end_minutes, nil] }] }, "\u00a0",
|
|
177
|
+
{
|
|
178
|
+
'cat' => ['Duration ',
|
|
179
|
+
{ 'formatHm' => { '%' => [{ '+' => [{ '-' => [end_minutes, start_minutes] }, 1440] }, 1440] } },
|
|
180
|
+
{ 'if' => [{ '<' => [end_minutes, start_minutes] }, ' (next day)', ''] }]
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
res.fields_text label: 'Start', name: 'user[start_time]', width: 300, onChange: duration_update
|
|
188
|
+
res.fields_text label: 'End', name: 'user[end_time]', width: 300, onChange: duration_update
|
|
189
|
+
res.spacer height: 8
|
|
190
|
+
res.label id: 'duration_label', text: 'PENDING'
|
|
156
191
|
end
|
|
157
192
|
)
|
|
158
193
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
json.title 'Test Page (panels_association)'
|
|
2
|
+
|
|
3
|
+
page = json_ui_page json
|
|
4
|
+
render 'json_ui/garage/test_page/header', json: json, page: page
|
|
5
|
+
|
|
6
|
+
# The panels_association fixture (spec 353, D5): doculocker's submission-form
|
|
7
|
+
# shape on dummy-app models, unpersisted so the page is deterministic against
|
|
8
|
+
# the dummy host's empty database. One un-indexed association (the signature
|
|
9
|
+
# form's singular nested model), two indexed associations each holding an
|
|
10
|
+
# indexed nested association (the qualification form's two-deep shape), a
|
|
11
|
+
# panels_responsive inside one (the signature form nests one), hidden id and
|
|
12
|
+
# visible text props, and a submit.
|
|
13
|
+
page.form \
|
|
14
|
+
url: json_ui_garage_url(path: 'forms/generic_post'),
|
|
15
|
+
model: Post.new(title: 'Fixture post'),
|
|
16
|
+
method: 'post',
|
|
17
|
+
padding: glib_json_padding_body,
|
|
18
|
+
childViews: ->(form) do
|
|
19
|
+
form.fields_text prop: :title, label: 'Post title'
|
|
20
|
+
|
|
21
|
+
form.h3 text: 'Unindexed association'
|
|
22
|
+
form.panels_association model: Comment.new(content: 'Lead comment'), width: 'matchParent', childViews: ->(assoc) do
|
|
23
|
+
assoc.fields_hidden prop: :id
|
|
24
|
+
assoc.panels_responsive width: 'matchParent', childViews: ->(responsive) do
|
|
25
|
+
responsive.fields_text prop: :content, label: 'Lead comment'
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
form.h3 text: 'Indexed associations'
|
|
30
|
+
[['First comment', 'first.pdf'], ['Second comment', 'second.pdf']].each_with_index do |(content, filename), index|
|
|
31
|
+
form.panels_association model: Comment.new(content: content), width: 'matchParent', order_index: index,
|
|
32
|
+
childViews: ->(comment) do
|
|
33
|
+
comment.fields_text prop: :content, label: "Comment #{index}"
|
|
34
|
+
comment.panels_association model: CommentFile.new(filename: filename), width: 'matchParent', order_index: 0,
|
|
35
|
+
childViews: ->(file) do
|
|
36
|
+
file.fields_text prop: :filename, label: "Comment #{index} file"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
form.fields_submit text: 'Submit'
|
|
42
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: glib-web
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.
|
|
4
|
+
version: 8.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ''
|
|
@@ -499,6 +499,7 @@ files:
|
|
|
499
499
|
- app/views/json_ui/garage/test_page/multimedia_video.json.jbuilder
|
|
500
500
|
- app/views/json_ui/garage/test_page/pagination.json.jbuilder
|
|
501
501
|
- app/views/json_ui/garage/test_page/panels.json.jbuilder
|
|
502
|
+
- app/views/json_ui/garage/test_page/panels_association.json.jbuilder
|
|
502
503
|
- app/views/json_ui/garage/test_page/panels_bulkEdit3.json.jbuilder
|
|
503
504
|
- app/views/json_ui/garage/test_page/popovers.json.jbuilder
|
|
504
505
|
- app/views/json_ui/garage/test_page/progressCircle.json.jbuilder
|