hot-glue 0.6.11 → 0.6.14
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/Gemfile.lock +5 -3
- data/README.md +15 -1
- data/app/helpers/hot_glue_helper.rb +8 -5
- data/lib/generators/hot_glue/field_factory.rb +2 -0
- data/lib/generators/hot_glue/fields/association_field.rb +26 -13
- data/lib/generators/hot_glue/fields/boolean_field.rb +3 -4
- data/lib/generators/hot_glue/fields/date_time_field.rb +1 -1
- data/lib/generators/hot_glue/fields/field.rb +5 -1
- data/lib/generators/hot_glue/fields/related_set_field.rb +1 -1
- data/lib/generators/hot_glue/markup_templates/erb.rb +11 -9
- data/lib/generators/hot_glue/scaffold_generator.rb +7 -3
- data/lib/generators/hot_glue/templates/controller.rb.erb +16 -5
- data/lib/generators/hot_glue/templates/erb/_list.erb +1 -1
- data/lib/generators/hot_glue/templates/erb/edit.erb +2 -1
- data/lib/hotglue/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e3938ec168ea29eb7311c82742601f1d19ceb5c670e909ddd6ab5efda1a8bca
|
4
|
+
data.tar.gz: 4a2a21046045ab745e0c2d3ba3b5faddab2507628e245d5caae159f9c6c8bca2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37aa5ce09632029e929cd9d085c48bab155ee4db0560e76d9a8bf9aac5ab541929fd604111674da4390383c123e3b7c53b2826a0a374e2de507f665bb440d49c
|
7
|
+
data.tar.gz: 50b1a2f1fac6ae0e144bb949c9febb63165a3eeec7d0780035998234e7b854631c949246c06886d0a75c9dc0baf83fe8103948981d2fec3167086ecff1c8fa34
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
hot-glue (0.6.
|
4
|
+
hot-glue (0.6.12)
|
5
5
|
ffaker (~> 2.16)
|
6
6
|
kaminari (~> 1.2)
|
7
7
|
rails (> 5.1)
|
@@ -76,6 +76,7 @@ GEM
|
|
76
76
|
tzinfo (~> 2.0)
|
77
77
|
addressable (2.8.1)
|
78
78
|
public_suffix (>= 2.0.2, < 6.0)
|
79
|
+
base64 (0.2.0)
|
79
80
|
bcrypt (3.1.18)
|
80
81
|
builder (3.2.4)
|
81
82
|
byebug (11.1.3)
|
@@ -139,7 +140,7 @@ GEM
|
|
139
140
|
mini_mime (1.1.2)
|
140
141
|
mini_portile2 (2.8.4)
|
141
142
|
minitest (5.16.3)
|
142
|
-
net-imap (0.5.
|
143
|
+
net-imap (0.5.5)
|
143
144
|
date
|
144
145
|
net-protocol
|
145
146
|
net-pop (0.1.2)
|
@@ -245,7 +246,8 @@ GEM
|
|
245
246
|
warden (1.2.9)
|
246
247
|
rack (>= 2.0.9)
|
247
248
|
websocket (1.2.9)
|
248
|
-
websocket-driver (0.7.
|
249
|
+
websocket-driver (0.7.7)
|
250
|
+
base64
|
249
251
|
websocket-extensions (>= 0.1.0)
|
250
252
|
websocket-extensions (0.1.5)
|
251
253
|
xpath (3.2.0)
|
data/README.md
CHANGED
@@ -674,7 +674,9 @@ Applies a badge `bg-primary` to rows with opened_at truthy and `bg-secondary` to
|
|
674
674
|
to display a badge on everything, use the `none` modifier with the
|
675
675
|
`--modify=opened_at{none}[bg-dark]`
|
676
676
|
|
677
|
+
For the `$` modifier only, if the field name ends with `_cents`, the modifier will automatically divide the field by 100 before displaying it.
|
677
678
|
|
679
|
+
(This is consistent with Stripe'e paradigm to always store money in cents, and this way I force myself to put `_cents` on the end of my field names to remind myself that they are in cents.)
|
678
680
|
|
679
681
|
### `--alt-foreign-key-lookup=`
|
680
682
|
|
@@ -1744,11 +1746,23 @@ If you have a partial in your view folder called `_list_after_each_row_heading`,
|
|
1744
1746
|
|
1745
1747
|
The `within` partials should do operations within the form (like hidden fields), and the `after` partials should do entirely unrelated operations, like a different form entirely.
|
1746
1748
|
|
1747
|
-
These automatic pickups for partials are detected at
|
1749
|
+
These automatic pickups for partials are detected at build time. This means that if you add these partials later, you must rebuild your scaffold.
|
1748
1750
|
|
1749
1751
|
|
1750
1752
|
# VERSION HISTORY
|
1751
1753
|
|
1754
|
+
#### 2025-02-28 - v0.6.14
|
1755
|
+
|
1756
|
+
• fixes bug in association field involving scaffolds built without nesting
|
1757
|
+
• fixes bug in paginated display
|
1758
|
+
• when applying $ modifier to a numerical field, if the field ends with `_cents`, the number will be /100 before being displayed
|
1759
|
+
|
1760
|
+
|
1761
|
+
#### 2025-02-20 - v0.6.12
|
1762
|
+
• adds decimal field type (displays as float-- there is no special handling for decimal on the UI)
|
1763
|
+
• guard against polymorphic belongs_to -- not a full implementation for polymorphic fields, just hides the fields on the form; on the list uses to_label always
|
1764
|
+
• fixes heading with multiword names on downnested portals to display nicely capitalized
|
1765
|
+
• removes open struct
|
1752
1766
|
|
1753
1767
|
#### 2025-01-28 v0.6.11
|
1754
1768
|
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module HotGlueHelper
|
2
|
-
|
3
|
-
|
2
|
+
class KVObject
|
3
|
+
attr_accessor :key, :value
|
4
|
+
def initialize(key: , value: )
|
5
|
+
@key = key
|
6
|
+
@value = value
|
7
|
+
end
|
8
|
+
end
|
4
9
|
|
5
10
|
def enum_to_collection_select(hash)
|
6
|
-
hash.collect{|k,v|
|
7
|
-
|
11
|
+
hash.collect{|k,v| KVObject.new(key: k, value: v)}
|
8
12
|
end
|
9
|
-
|
10
13
|
end
|
@@ -24,17 +24,18 @@ class AssociationField < Field
|
|
24
24
|
raise(HotGlue::Error, exit_message)
|
25
25
|
end
|
26
26
|
|
27
|
-
|
27
|
+
if ! eval("#{class_name}.reflect_on_association(:#{assoc}).polymorphic?")
|
28
|
+
@assoc_class = eval(assoc_model.try(:class_name))
|
28
29
|
|
29
|
-
|
30
|
+
name_list = [:name, :to_label, :full_name, :display_name, :email]
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
if assoc_class && name_list.collect{ |field|
|
33
|
+
assoc_class.respond_to?(field.to_s) || assoc_class.instance_methods.include?(field)
|
34
|
+
}.none?
|
35
|
+
exit_message = "Oops: Missing a label for `#{assoc_class}`. Can't find any column to use as the display label for the #{@assoc_name} association on the #{class_name} model. TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name 5) email. You can implement any of these directly on your`#{assoc_class}` model (can be database fields or model methods) or alias them to field you want to use as your display label. Then RERUN THIS GENERATOR. (Field used will be chosen based on rank here.)"
|
36
|
+
raise(HotGlue::Error, exit_message)
|
37
|
+
end
|
36
38
|
end
|
37
|
-
|
38
39
|
end
|
39
40
|
|
40
41
|
def assoc_label
|
@@ -111,8 +112,8 @@ class AssociationField < Field
|
|
111
112
|
# end
|
112
113
|
elsif modify_as && modify_as[:typeahead]
|
113
114
|
search_url = "#{namespace ? namespace + "_" : ""}" +
|
114
|
-
modify_as[:nested].join("_") +
|
115
|
-
+ "
|
115
|
+
modify_as[:nested].join("_") + ( modify_as[:nested].any? ? "_" : "") +
|
116
|
+
+ "#{assoc.class_name.downcase.pluralize}_typeahead_index_url"
|
116
117
|
|
117
118
|
|
118
119
|
if @modify_as[:nested].any?
|
@@ -140,7 +141,12 @@ class AssociationField < Field
|
|
140
141
|
|
141
142
|
is_owner = name == ownership_field
|
142
143
|
assoc_class_name = assoc.class_name.to_s
|
143
|
-
|
144
|
+
if assoc_class
|
145
|
+
display_column = HotGlue.derrive_reference_name(assoc_class_name)
|
146
|
+
else
|
147
|
+
# polymorphic
|
148
|
+
display_column = "name"
|
149
|
+
end
|
144
150
|
|
145
151
|
if hawk_keys[assoc.foreign_key.to_sym]
|
146
152
|
hawk_definition = hawk_keys[assoc.foreign_key.to_sym]
|
@@ -178,9 +184,16 @@ class AssociationField < Field
|
|
178
184
|
|
179
185
|
def line_field_output
|
180
186
|
|
181
|
-
display_column = HotGlue.derrive_reference_name(assoc_class.to_s)
|
182
187
|
|
183
|
-
|
188
|
+
if assoc_class
|
189
|
+
display_column = HotGlue.derrive_reference_name(assoc_class.to_s)
|
190
|
+
|
191
|
+
"<%= #{singular}.#{assoc}.try(:#{display_column}) || '<span class=\"content \">MISSING</span>'.html_safe %>"
|
192
|
+
else
|
193
|
+
"<%= #{singular}.#{assoc}.try(:to_label) || '<span class=\"content \">MISSING</span>'.html_safe %>"
|
194
|
+
|
195
|
+
end
|
196
|
+
|
184
197
|
end
|
185
198
|
|
186
199
|
|
@@ -40,19 +40,18 @@ class BooleanField < Field
|
|
40
40
|
if display_boolean_as.nil?
|
41
41
|
|
42
42
|
end
|
43
|
-
"<
|
43
|
+
"<span class='#{@layout_strategy.form_checkbox_wrapper_class} #{'form-switch' if display_boolean_as == 'switch'}'>\n" +
|
44
44
|
(if display_boolean_as == 'radio'
|
45
45
|
radio_button_display
|
46
46
|
elsif display_boolean_as == 'checkbox'
|
47
47
|
checkbox_display
|
48
48
|
elsif display_boolean_as == 'switch'
|
49
49
|
switch_display
|
50
|
-
end) + "</
|
50
|
+
end) + "</span> \n"
|
51
51
|
end
|
52
52
|
|
53
53
|
def form_field_output
|
54
|
-
|
55
|
-
form_field_display + (form_labels_position == 'after' ? " <br />" : "")
|
54
|
+
form_field_display
|
56
55
|
end
|
57
56
|
|
58
57
|
def line_field_output
|
@@ -40,7 +40,7 @@ class DateTimeField < Field
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def form_field_output
|
43
|
-
"<%= f.datetime_field( :#{name}, value: #{singular}.#{name} && #{singular}.#{name}.
|
43
|
+
"<%= f.datetime_field( :#{name}, value: #{singular}.#{name} && #{singular}.#{name}.in_time_zone(current_timezone), class: '#{@layout_strategy.form_input_class}' ) %><%= current_timezone %>"
|
44
44
|
end
|
45
45
|
|
46
46
|
def viewable_output
|
@@ -145,7 +145,11 @@ class Field
|
|
145
145
|
res = +''
|
146
146
|
|
147
147
|
if modify_as[:cast] && modify_as[:cast] == "$"
|
148
|
-
|
148
|
+
if name.ends_with?("_cents")
|
149
|
+
res += "<%= number_to_currency(#{singular}.#{name} / 100) %>"
|
150
|
+
else
|
151
|
+
res += "<%= number_to_currency(#{singular}.#{name}) %>"
|
152
|
+
end
|
149
153
|
elsif modify_as[:binary]
|
150
154
|
res += "<%= #{singular}.#{name} ? '#{modify_as[:binary][:truthy]}' : '#{modify_as[:binary][:falsy]}' %>"
|
151
155
|
elsif modify_as[:tinymce]
|
@@ -3,7 +3,7 @@ class RelatedSetField < Field
|
|
3
3
|
attr_accessor :assoc_name, :assoc_class, :assoc
|
4
4
|
|
5
5
|
def initialize( class_name: , default_boolean_display:, display_as: ,
|
6
|
-
name: , singular: ,
|
6
|
+
name: , singular: , plural:,
|
7
7
|
alt_lookup: ,
|
8
8
|
update_show_only: ,
|
9
9
|
hawk_keys: , auth: , sample_file_path:, ownership_field: ,
|
@@ -156,18 +156,20 @@ module HotGlue
|
|
156
156
|
"<% if @action == 'new' && policy(@#{singular}).#{col}_able? %>" + columns_map[col].form_field_output + "<% else %>" + columns_map[col].form_show_only_output + "<% end %>"
|
157
157
|
|
158
158
|
# show only on the update action overrides any pundit policy
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
159
|
+
elsif @pundit && eval("defined? #{singular_class}Policy") && eval("#{singular_class}Policy").instance_methods.include?("#{col}_able?".to_sym)
|
160
|
+
"<% if policy(@#{singular}).#{col}_able? %>" + columns_map[col].form_field_output + "<% else %>" + columns_map[col].form_show_only_output + "<% end %>"
|
161
|
+
else
|
162
|
+
columns_map[col].form_field_output
|
163
|
+
end
|
164
|
+
|
164
165
|
|
165
166
|
@tinymce_stimulus_controller = (columns_map[col].modify_as == {tinymce: 1} ? "data-controller='tiny-mce' " : "")
|
167
|
+
|
166
168
|
add_spaces_each_line( "\n <span #{@tinymce_stimulus_controller}class='<%= \"alert alert-danger\" if #{singular}.errors.details.keys.include?(:#{field_error_name}) %>' #{'style="display: inherit;"'} >\n" +
|
167
|
-
add_spaces_each_line( (form_labels_position == 'before' ? the_label || "" : "") +
|
168
|
-
+
|
169
|
-
(form_labels_position == 'after' ? the_label : "")
|
170
|
-
"\n </span>\n
|
169
|
+
add_spaces_each_line( (form_labels_position == 'before' ? (the_label || "") + "<br />\n" : "") +
|
170
|
+
+ field_result +
|
171
|
+
(form_labels_position == 'after' ? "<br />\n" + (the_label || "") : "") , 4) +
|
172
|
+
"\n </span>\n ", 2)
|
171
173
|
|
172
174
|
}.join("") + "\n </div>"
|
173
175
|
}.join("\n")
|
@@ -81,7 +81,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
81
81
|
class_option :form_placeholder_labels, type: :boolean, default: false # puts the field names into the placeholder labels
|
82
82
|
|
83
83
|
# determines if labels appear within the rows of the VIEWABLE list (does NOT affect the list heading)
|
84
|
-
class_option :inline_list_labels, default:
|
84
|
+
class_option :inline_list_labels, default: nil # default is set below
|
85
85
|
class_option :factory_creation, default: ''
|
86
86
|
class_option :alt_foreign_key_lookup, default: '' #
|
87
87
|
class_option :attachments, default: ''
|
@@ -262,7 +262,11 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
262
262
|
elsif $2 == "tinymce"
|
263
263
|
@modify_as[key.to_sym] = {tinymce: 1, badges: $3}
|
264
264
|
elsif $2 == "typeahead"
|
265
|
-
|
265
|
+
if !$3.nil?
|
266
|
+
nested = $3.split("/")
|
267
|
+
else
|
268
|
+
nested = []
|
269
|
+
end
|
266
270
|
@modify_as[key.to_sym] = {typeahead: 1, nested: nested}
|
267
271
|
elsif $2 == "timezone"
|
268
272
|
@modify_as[key.to_sym] = {timezone: 1, badges: $3}
|
@@ -303,7 +307,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
303
307
|
|
304
308
|
setup_hawk_keys
|
305
309
|
@form_placeholder_labels = options['form_placeholder_labels'] # true or false
|
306
|
-
@inline_list_labels = options['inline_list_labels'] || 'omit' # 'before','after','omit'
|
310
|
+
@inline_list_labels = options['inline_list_labels'] || get_default_from_config(key: :inline_list_labels) || 'omit' # 'before','after','omit'
|
307
311
|
|
308
312
|
@form_labels_position = options['form_labels_position']
|
309
313
|
if !['before', 'after', 'omit'].include?(@form_labels_position)
|
@@ -72,13 +72,14 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
72
72
|
params[:per] || 10
|
73
73
|
end<% end %>
|
74
74
|
<% unless @no_list %>
|
75
|
-
def load_all_<%= plural %>
|
75
|
+
def load_all_<%= plural %><% if @search == "set" %>
|
76
|
+
@q = params[:q] || <%= {"0" => @search_fields.collect{|foo| {"#{foo}_match".to_sym => ((@columns_map[foo.to_sym].modify_as && @columns_map[foo.to_sym].modify_as[:binary]) ? "-1" : ""), "#{foo}_search".to_sym => ""}}.reduce({}, :merge) } %> <% end %>
|
76
77
|
<%= load_all_code %>
|
77
78
|
end
|
78
79
|
|
79
|
-
def index
|
80
|
-
|
81
|
-
|
80
|
+
def index
|
81
|
+
load_all_<%= plural %>
|
82
|
+
<% if @search_fields %>
|
82
83
|
<%= @search_fields.collect{|field_name| @columns_map[field_name.to_sym].code_to_reset_match_if_search_is_blank}.compact.join(" \n") %><% end %>
|
83
84
|
load_all_<%= plural %><% if @pundit %><% if @pundit %>
|
84
85
|
authorize @<%= plural_name %><% end %>
|
@@ -131,8 +132,18 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
131
132
|
<% unless @display_edit_after_create %>render :create, status: :unprocessable_entity<% else %>render :new , status: :unprocessable_entity<% end %>
|
132
133
|
end<% if @pundit %>
|
133
134
|
rescue Pundit::NotAuthorizedError => e
|
135
|
+
flash[:alert] = "Not authorized."
|
134
136
|
@<%= singular %>.errors.add(:base, e.message)
|
135
|
-
render :create, status: :unprocessable_entity<%
|
137
|
+
<% unless @display_edit_after_create %>render :create, status: :unprocessable_entity<% else %>redirect_to <%= HotGlue.optionalized_ternary(namespace: @namespace,
|
138
|
+
top_level: true,
|
139
|
+
target: @singular,
|
140
|
+
nested_set: @nested_set,
|
141
|
+
modifier: 'edit_',
|
142
|
+
with_params: true,
|
143
|
+
instance_last_item: true,
|
144
|
+
put_form: true).gsub("(#{singular}", "(@#{singular}") %><% end %>
|
145
|
+
|
146
|
+
<% end %>
|
136
147
|
end
|
137
148
|
|
138
149
|
<% end %>
|
@@ -61,7 +61,7 @@
|
|
61
61
|
%>
|
62
62
|
<\% end %>
|
63
63
|
<% if @paginate_per_page_selector %>
|
64
|
-
<\%= form_with url:
|
64
|
+
<\%= form_with url: '<%= path_helper_plural(top_level: false) %>', method: :get do |f| %>
|
65
65
|
Show per page
|
66
66
|
<\%= f.collection_select "per", [10, 25, 100], :to_s, :to_s, {prompt: true, selected: params[:per]}, {onChange: "this.form.submit();"} %>
|
67
67
|
<\% end %>
|
@@ -11,6 +11,7 @@
|
|
11
11
|
|
12
12
|
|
13
13
|
<% if @downnest_children.any? && @big_edit %>
|
14
|
+
<hr />
|
14
15
|
<% each_downnest_width = @downnest_children.count == 1 ? 33 : (53/@downnest_children.count).floor %>
|
15
16
|
<% @downnest_object.each do |downnest, size| %>
|
16
17
|
<div class="row">
|
@@ -22,7 +23,7 @@
|
|
22
23
|
<% downnest_style = @layout_strategy.downnest_style %>
|
23
24
|
<% if @downnest_shows_headings %>
|
24
25
|
<h3>
|
25
|
-
<%= downnest_class.
|
26
|
+
<%= downnest_class.titlecase.pluralize %>
|
26
27
|
</h3>
|
27
28
|
<% end %>
|
28
29
|
<\%= render partial: "<%= namespace_with_trailing_dash %><%= downnest_object_name %>/list", locals: {<%= @singular %>: @<%= @singular %>, <%= downnest_object_name %>: @<%= @singular %>.<%= downnest %><% if @nested_set.any? %>, <%= @nested_set.collect{|x| "#{x[:singular]}: @#{x[:singular]}"}.join(", ") %>, nested_for: "<%= @nested_set.collect{|x| "#{x[:singular]}-" + "\#{" + "@#{x[:singular]}.id}"}.join("__") %>__<%= singular %>-#{@<%= @singular %>.id}" <% end %> } \%>
|
data/lib/hotglue/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hot-glue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Fleetwood-Boldt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|