hot-glue 0.6.14 → 0.6.16

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: 3e3938ec168ea29eb7311c82742601f1d19ceb5c670e909ddd6ab5efda1a8bca
4
- data.tar.gz: 4a2a21046045ab745e0c2d3ba3b5faddab2507628e245d5caae159f9c6c8bca2
3
+ metadata.gz: '09ebf223206d1bf224f02aaafe2796774bfa6b3d61c6892c1b0144ec2a8dd0f3'
4
+ data.tar.gz: 1fd04b5e1909ebcf2ecc9eeb5c4e212f7a6878d49c0fe918305e43e441cd73d3
5
5
  SHA512:
6
- metadata.gz: 37aa5ce09632029e929cd9d085c48bab155ee4db0560e76d9a8bf9aac5ab541929fd604111674da4390383c123e3b7c53b2826a0a374e2de507f665bb440d49c
7
- data.tar.gz: 50b1a2f1fac6ae0e144bb949c9febb63165a3eeec7d0780035998234e7b854631c949246c06886d0a75c9dc0baf83fe8103948981d2fec3167086ecff1c8fa34
6
+ metadata.gz: c01e39699fe999a7024850b9d738d5e205b4e5abe8c39d3619d10efa74fbed2384ac6cadfa4010d52c0a9fdea3878ae599aa23002cd439d323701f4b8524c3eb
7
+ data.tar.gz: 79c20e1f78772f79e396cecfc81990a70b3a0d17988962baebd6c2ea0b10eabedea59ebd8624f34d0ad7ce864d59bf7ad7be2afb8c712ef01f605ab06e272fce
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hot-glue (0.6.12)
4
+ hot-glue (0.6.15)
5
5
  ffaker (~> 2.16)
6
6
  kaminari (~> 1.2)
7
7
  rails (> 5.1)
@@ -140,14 +140,14 @@ GEM
140
140
  mini_mime (1.1.2)
141
141
  mini_portile2 (2.8.4)
142
142
  minitest (5.16.3)
143
- net-imap (0.5.5)
143
+ net-imap (0.5.6)
144
144
  date
145
145
  net-protocol
146
146
  net-pop (0.1.2)
147
147
  net-protocol
148
148
  net-protocol (0.2.2)
149
149
  timeout
150
- net-smtp (0.5.0)
150
+ net-smtp (0.5.1)
151
151
  net-protocol
152
152
  nio4r (2.5.8)
153
153
  nokogiri (1.13.9)
data/README.md CHANGED
@@ -790,6 +790,23 @@ end
790
790
  Because Hot Glue detects the `*_able?` methods at build time, if you add them to your policy, you will have to rebuild your scaffold.
791
791
 
792
792
 
793
+ ### `--pundit-policy-override`
794
+ if you use the flag `--pundit-policy-override` your controller operations will bypass the invisible (pundit provided) access control and use the pundit policy you specify.
795
+
796
+ example
797
+
798
+ `rails generate hot_glue:scaffold Invoice --gd --pundit-policy-override='UniqueInvoicePolicy'`
799
+
800
+ You will implement a Pundit policy for `UniqueInvoicePolicy` and it should implement actions with question mark `?` endings corresponding to the same actions you are building, `new?`, `create?`, `edit?`, `update?`, and `destroy?`
801
+
802
+ If provided, the output code looks something like (in this example, showing the `edit?` method)
803
+
804
+ ```
805
+ skip_authorization
806
+ raise Pundit::NotAuthorizedError if ! UniqueInvoicePolicy.edit?
807
+ ```
808
+
809
+
793
810
  ### `--show-only=`
794
811
  (separate field names by COMMA)
795
812
 
@@ -1751,6 +1768,46 @@ These automatic pickups for partials are detected at build time. This means that
1751
1768
 
1752
1769
  # VERSION HISTORY
1753
1770
 
1771
+ #### 2025-03-31 v0.6.16
1772
+
1773
+ • Bootstrap Tab Panes For Downnested Portals
1774
+ Downnested portals are now built with bootstrap tab panes (always) and are no longer stacked on top of one another.
1775
+
1776
+ It looks like this:
1777
+ https://getbootstrap.com/docs/5.0/components/navs-tabs/#javascript-behavior
1778
+
1779
+ • inline_list_labels can be set in hot_glue.yml
1780
+ • typeaheads nested inside of routes are fixed
1781
+ • switches back to current_timezone implementation, displaying times relative to the user's set timezone
1782
+ • load all code now sets query parameters
1783
+
1784
+ • Pundit Policy Override
1785
+ if you use the flag `--pundit-policy-override` your controller operations will bypass the invisible (pundit provided) access control and use the pundit policy you specify.
1786
+
1787
+ example
1788
+
1789
+ `rails generate hot_glue:scaffold Invoice --gd --pundit-policy-override='UniqueInvoicePolicy'`
1790
+
1791
+ Implement `UniqueInvoicePolicy` using actions with question mark `?` endings corresponding to the same actions you are building, `new?`, `create?`, `edit?`, `update?`, and `destroy?`
1792
+
1793
+
1794
+ • Bootstrap column builder has been changed.
1795
+ The bootstrap column bulder previously defaulted all real columns to col-sm-2 (or whichever bootstrap column with you set)
1796
+
1797
+ The builder has been refactored to allow for a per-column width generated automatically by the builder. If there are unused bootstrap columns, the builder will add width to the first columns in your layout, making them wider.
1798
+
1799
+
1800
+
1801
+
1802
+
1803
+
1804
+ #### 2025-03-17 - v0.6.15
1805
+
1806
+ • now store on your current_user model (this is automatically passed into the method modify_date_inputs_on_params). HG will set user-inputted values correctly to daylight savings time during April-Nov months only (#195)
1807
+ • fixes issue with turbo frame name after create is rendered (#194)
1808
+ • removes vestigates of optionalized partents
1809
+
1810
+
1754
1811
  #### 2025-02-28 - v0.6.14
1755
1812
 
1756
1813
  • fixes bug in association field involving scaffolds built without nesting
@@ -68,8 +68,16 @@ module HotGlue
68
68
  end
69
69
  end
70
70
 
71
+ def is_dst_now?
72
+ Time.now.utc.month > 3 && Time.now.month < 11 ||
73
+ (Time.now.utc.month == 3 && Time.now.day >= (14 - Time.now.utc.wday)) ||
74
+ (Time.now.utc.month == 11 && Time.now.utc.day < (7 - Time.now.utc.wday))
75
+ end
76
+
71
77
  def modify_date_inputs_on_params(modified_params, current_user_object = nil, field_list = nil)
72
78
  use_timezone = (current_user_object.try(:timezone)) || Time.zone
79
+ uses_dst = (current_user_object.try(:locale_uses_dst)) || false
80
+
73
81
  modified_params = modified_params.tap do |params|
74
82
  params.keys.each{|k|
75
83
 
@@ -88,7 +96,9 @@ module HotGlue
88
96
  # if they already exist in your database, you should zero them out
89
97
  # or apply .change(sec: 0) when displaying them as output in the form
90
98
  # this will prevent seconds from being added by the browser
91
- params[k] = Time.strptime(parse_date, "%Y-%m-%d %H:%M %Z")
99
+ parsed_time = Time.strptime(parse_date, "%Y-%m-%d %H:%M %Z")
100
+ parsed_time = parsed_time.to_time - 60.minutes if uses_dst && is_dst_now?
101
+ params[k] = parsed_time
92
102
  end
93
103
  end
94
104
  }
@@ -12,8 +12,6 @@ require_relative "fields/uuid_field"
12
12
  require_relative "fields/attachment_field"
13
13
  require_relative "fields/related_set_field"
14
14
 
15
-
16
-
17
15
  class FieldFactory
18
16
  attr_accessor :field, :class_name
19
17
  def initialize(type: , name: , generator: )
@@ -51,6 +49,9 @@ class FieldFactory
51
49
  end
52
50
  @class_name = class_name
53
51
 
52
+ if field_class.nil?
53
+ raise "Field type could be identified #{name} "
54
+ end
54
55
 
55
56
  @field = field_class.new(name: name,
56
57
  layout_strategy: generator.layout_strategy,
@@ -155,6 +155,7 @@ class AssociationField < Field
155
155
  hawked_association = "#{assoc.class_name}.all"
156
156
  end
157
157
 
158
+
158
159
  (is_owner ? "<% unless @#{assoc_name} %>\n" : "") +
159
160
  " <%= f.collection_select(:#{name}, #{hawked_association}, :id, :#{display_column}, {prompt: true, selected: #{singular}.#{name} }, class: 'form-control') %>\n" +
160
161
  (is_owner ? "<% else %>\n <%= @#{assoc_name}.#{display_column} %>" : "") +
@@ -253,6 +254,13 @@ class AssociationField < Field
253
254
  # "\n "
254
255
  end
255
256
 
257
+ def newline_after_field?
258
+ if modify_as && modify_as[:typeahead]
259
+ false
260
+ else
261
+ true
262
+ end
263
+ end
256
264
 
257
265
  def where_query_statement
258
266
  ".where(*#{name}_query)"
@@ -32,6 +32,7 @@ class EnumField < Field
32
32
 
33
33
  def form_field_output
34
34
  enum_type = eval("#{class_name}.columns.select{|x| x.name == '#{name}'}[0].sql_type")
35
+
35
36
  if eval("defined? #{class_name}.#{enum_type}_labels") == "method"
36
37
  enum_definer = "#{class_name}.#{enum_type}_labels"
37
38
  else
@@ -219,4 +219,9 @@ class Field
219
219
  def code_to_reset_match_if_search_is_blank
220
220
  nil
221
221
  end
222
+
223
+ def newline_after_field?
224
+ false
225
+ end
226
+
222
227
  end
@@ -40,7 +40,8 @@ module HotGlue
40
40
  layout_object = {
41
41
  columns: {
42
42
  size_each: smart_layout ? bootstrap_column_width : (specified_grouping_mode ? nil : 1),
43
- container: [] # array of arrays
43
+ container: [] , # array of arrays,
44
+ bootstrap_column_width: []
44
45
  },
45
46
  portals: {
46
47
 
@@ -99,7 +100,7 @@ module HotGlue
99
100
  }
100
101
  layout_object[:columns][:container] = (0..available_columns-1).collect { |x| [columns[x]] }
101
102
  layout_object[:columns][:container].reject!{|x| x == [nil]}
102
- layout_object[:columns][:size_each] = bootstrap_column_width
103
+ # layout_object[:columns][:size_each] = bootstrap_column_width
103
104
  end
104
105
  elsif ! specified_grouping_mode
105
106
  # not smart and no specified grouping
@@ -117,22 +118,33 @@ module HotGlue
117
118
  # input control
118
119
 
119
120
  user_layout_columns = @include_setting.split(":")
120
- size_each = (bootstrap_columns / user_layout_columns.count).floor # this is the bootstrap size
121
121
 
122
- layout_object[:columns][:size_each] = size_each
122
+ extra_columns = available_columns - user_layout_columns.size
123
+ # size_each = (bootstrap_columns / user_layout_columns.count).floor # this is the bootstrap size
124
+ #
125
+ # layout_object[:columns][:size_each] = size_each
123
126
 
124
- if user_layout_columns.size > available_columns
125
- raise "Your include statement #{@include_setting } has #{user_layout_columns.size} columns, but I can only construct up to #{available_columns}"
126
- end
127
+ # if user_layout_columns.size > available_columns
128
+ # raise "Your include statement #{@include_setting } has #{user_layout_columns.size} columns, but I can only construct up to #{available_columns}"
129
+ # end
127
130
  user_layout_columns.each_with_index do |column,i|
128
131
  layout_object[:columns][:container][i] = column.split(",").collect(&:to_sym)
132
+
133
+ default_col_width = 1
134
+ if extra_columns > 0
135
+ default_col_width += 1
136
+ extra_columns -= 1
137
+ end
138
+ layout_object[:columns][:bootstrap_column_width][i] = default_col_width
129
139
  end
130
140
 
131
141
  if user_layout_columns.size < layout_object[:columns][:container].size
132
142
  layout_object[:columns][:container].reject!{|x| x == []}
133
143
  end
144
+
134
145
  end
135
146
 
147
+
136
148
  puts "*** constructed smart layout columns #{layout_object.inspect}"
137
149
  layout_object
138
150
  end
@@ -17,20 +17,20 @@ class LayoutStrategy::Bootstrap < LayoutStrategy::Base
17
17
  end
18
18
 
19
19
 
20
- def column_classes_for_form_fields
21
- "col-md-#{builder.layout_object[:columns][:size_each]}"
20
+ def column_classes_for_form_fields(size = nil)
21
+ "col-md-#{size || builder.layout_object[:columns][:size_each]}"
22
22
  end
23
23
 
24
- def column_classes_for_column_headings
25
- column_classes_for_line_fields
24
+ def column_classes_for_column_headings(size = nil)
25
+ column_classes_for_line_fields(size)
26
26
  end
27
27
 
28
28
  def container_name
29
29
  "container"
30
30
  end
31
31
 
32
- def column_classes_for_line_fields
33
- "col-sm-#{builder.layout_object[:columns][:size_each]}"
32
+ def column_classes_for_line_fields(size = nil)
33
+ "col-sm-#{size || builder.layout_object[:columns][:size_each]}"
34
34
  end
35
35
 
36
36
  def column_width
@@ -39,18 +39,18 @@ class LayoutStrategy::HotGlue < LayoutStrategy::Base
39
39
  "scaffold-row"
40
40
  end
41
41
 
42
- def column_classes_for_form_fields
42
+ def column_classes_for_form_fields(size = nil)
43
43
  "scaffold-cell"
44
44
  end
45
45
 
46
46
  def row_heading_classes
47
47
  "scaffold-heading-row"
48
48
  end
49
- def column_classes_for_line_fields
49
+ def column_classes_for_line_fields(size = nil)
50
50
  "scaffold-cell"
51
51
  end
52
52
 
53
- def column_classes_for_column_headings
53
+ def column_classes_for_column_headings(size = nil)
54
54
  "scaffold-cell"
55
55
  end
56
56
 
@@ -6,9 +6,9 @@ class LayoutStrategy::Tailwind < LayoutStrategy::Base
6
6
  def button_style ; ""; end
7
7
  def column_headings_col_style; "" ; end
8
8
  def column_width; ""; end
9
- def column_classes_for_line_fields; ""; end
10
- def column_classes_for_form_fields; ""; end
11
- def column_classes_for_column_headings; ""; end
9
+ def column_classes_for_line_fields(size = nil); ""; end
10
+ def column_classes_for_form_fields(size = nil); ""; end
11
+ def column_classes_for_column_headings(size = nil); ""; end
12
12
  def col_width; 100; end
13
13
  def container_name; ""; end
14
14
  def downnest_style ; ""; end
@@ -76,13 +76,14 @@ module HotGlue
76
76
  }.join("\n")
77
77
  end
78
78
 
79
- def list_column_headings(col_identifier: ,
80
- column_width:, singular: )
79
+ def list_column_headings(column_width:, singular: )
81
80
  col_style = @layout_strategy.column_headings_col_style
82
81
 
83
82
  columns = layout_object[:columns][:container]
84
- result = columns.map{ |column|
85
- "<div class='#{col_identifier} hg-heading-row heading--#{singular}--#{column.join("-")}' " + col_style + ">" +
83
+ result = columns.map.with_index{ |column,i|
84
+
85
+ size = layout_object[:columns][:bootstrap_column_width][i]
86
+ "<div class='#{layout_strategy.column_classes_for_column_headings(size)} hg-heading-row heading--#{singular}--#{column.join("-")}' " + col_style + ">" +
86
87
  column.map(&:to_s).map{|col_name| "#{col_name.humanize}"}.join("<br />") + "</div>"
87
88
  }.join("\n")
88
89
  return result
@@ -95,7 +96,6 @@ module HotGlue
95
96
 
96
97
  def search_input_area
97
98
  columns = layout_object[:columns][:container]
98
- column_classes = layout_strategy.column_classes_for_form_fields
99
99
 
100
100
  res =+ "<\%= form_with url: #{form_path}, method: :get, html: {'data-turbo-action': 'advance', 'data-controller': 'search-form'} do |f| %>"
101
101
  res << "<div class=\"#{@layout_strategy.row_classes} search--#{@plural}\">"
@@ -116,12 +116,13 @@ module HotGlue
116
116
  end
117
117
  }.compact.join("\n")
118
118
 
119
- " <div class='#{column_classes} search-cell--#{singular}--#{column.join("-")}' >" +
119
+ size = layout_object[:columns][:bootstrap_column_width][columns.index(column)]
120
+ " <div class='#{layout_strategy.column_classes_for_form_fields(size)} search-cell--#{singular}--#{column.join("-")}' >" +
120
121
  cols_result + "</div>"
121
122
 
122
123
  }.join("\n")
123
124
  res << "</div>"
124
- res << "<div class='#{column_classes}'>"
125
+ res << "<div class='#{layout_strategy.column_classes_for_form_fields(nil)}'>"
125
126
  if @search_clear_button
126
127
  res << "<\%= f.button \"Clear\", name: nil, 'data-search-form-target': 'clearButton', class: 'btn btn-sm btn-secondary' %>"
127
128
  end
@@ -132,11 +133,12 @@ module HotGlue
132
133
 
133
134
 
134
135
  def all_form_fields(layout_strategy:)
135
- column_classes = layout_strategy.column_classes_for_form_fields
136
136
  columns = layout_object[:columns][:container]
137
137
 
138
138
  result = columns.map{ |column|
139
- " <div class='#{column_classes} cell--#{singular}--#{column.join("-")}' >" +
139
+ size = layout_object[:columns][:bootstrap_column_width][columns.index(column)]
140
+
141
+ " <div class='#{layout_strategy.column_classes_for_form_fields(size)} cell--#{singular}--#{column.join("-")}' >" +
140
142
  column.map { |col|
141
143
 
142
144
  field_error_name = columns_map[col].field_error_name
@@ -158,6 +160,8 @@ module HotGlue
158
160
  # show only on the update action overrides any pundit policy
159
161
  elsif @pundit && eval("defined? #{singular_class}Policy") && eval("#{singular_class}Policy").instance_methods.include?("#{col}_able?".to_sym)
160
162
  "<% if policy(@#{singular}).#{col}_able? %>" + columns_map[col].form_field_output + "<% else %>" + columns_map[col].form_show_only_output + "<% end %>"
163
+ elsif update_show_only.include?(col)
164
+ "<% if @action == 'edit' %>" + columns_map[col].form_show_only_output + "<% else %>" + columns_map[col].form_field_output + "<% end %>"
161
165
  else
162
166
  columns_map[col].form_field_output
163
167
  end
@@ -168,7 +172,7 @@ module HotGlue
168
172
  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" +
169
173
  add_spaces_each_line( (form_labels_position == 'before' ? (the_label || "") + "<br />\n" : "") +
170
174
  + field_result +
171
- (form_labels_position == 'after' ? "<br />\n" + (the_label || "") : "") , 4) +
175
+ (form_labels_position == 'after' ? ( columns_map[col].newline_after_field? ? "<br />\n" : "") + (the_label || "") : "") , 4) +
172
176
  "\n </span>\n ", 2)
173
177
 
174
178
  }.join("") + "\n </div>"
@@ -190,10 +194,8 @@ module HotGlue
190
194
  ################################################################
191
195
 
192
196
  def all_line_fields(layout_strategy:,
193
- perc_width:,
194
- col_identifier: nil)
197
+ perc_width:)
195
198
 
196
- @col_identifier = layout_strategy.column_classes_for_line_fields
197
199
 
198
200
  inline_list_labels = @inline_list_labels || 'omit'
199
201
  columns = layout_object[:columns][:container]
@@ -203,9 +205,11 @@ module HotGlue
203
205
 
204
206
  style_with_flex_basis = layout_strategy.style_with_flex_basis(perc_width)
205
207
 
206
- result = columns.map{ |column|
208
+ result = columns.map.with_index{ |column,i|
209
+
210
+ size = layout_object[:columns][:bootstrap_column_width][i]
207
211
 
208
- "<div class='hg-col #{col_identifier} #{singular}--#{column.join("-")}'#{style_with_flex_basis}> " +
212
+ "<div class='hg-col #{layout_strategy.column_classes_for_line_fields(size)} #{singular}--#{column.join("-")}'#{style_with_flex_basis}> " +
209
213
  column.map { |col|
210
214
  if eval("#{singular_class}.columns_hash['#{col}']").nil? && !attachments.keys.include?(col) && !related_sets.include?(col)
211
215
  raise "Can't find column '#{col}' on #{singular_class}, are you sure that is the column name?"
@@ -217,6 +221,8 @@ module HotGlue
217
221
  "#{inline_list_labels == 'before' ? label + "<br/>" : ''}#{field_output}#{inline_list_labels == 'after' ? "<br/>" + label : ''}"
218
222
  }.join( "<br />") + "</div>"
219
223
  }.join("\n")
224
+ return result
225
+
220
226
  end
221
227
  end
222
228
  end
@@ -77,7 +77,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
77
77
  class_option :no_list_heading, type: :boolean, default: false
78
78
 
79
79
  # determines if the labels show up BEFORE or AFTER on the NEW/EDIT (form)
80
- class_option :form_labels_position, type: :string, default: 'after' # choices are before, after, omit
80
+ class_option :form_labels_position, type: :string # choices are before, after, omit
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)
@@ -91,6 +91,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
91
91
  class_option :modify, default: {}
92
92
  class_option :display_as, default: {}
93
93
  class_option :pundit, default: nil
94
+ class_option :pundit_policy_override, default: nil
94
95
  class_option :related_sets, default: ''
95
96
  class_option :code_before_create, default: nil
96
97
  class_option :code_after_create, default: nil
@@ -310,10 +311,18 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
310
311
  @inline_list_labels = options['inline_list_labels'] || get_default_from_config(key: :inline_list_labels) || 'omit' # 'before','after','omit'
311
312
 
312
313
  @form_labels_position = options['form_labels_position']
313
- if !['before', 'after', 'omit'].include?(@form_labels_position)
314
- raise HotGlue::Error, "You passed '#{@form_labels_position}' as the setting for --form-labels-position but the only allowed options are before, after (default), and omit"
314
+ if @form_labels_position.nil?
315
+ @form_labels_position = get_default_from_config(key: :form_labels_position)
316
+ if @form_labels_position.nil?
317
+ @form_labels_position = 'after'
318
+ end
319
+ else
320
+ if !['before', 'after', 'omit'].include?(@form_labels_position)
321
+ raise HotGlue::Error, "You passed '#{@form_labels_position}' as the setting for --form-labels-position but the only allowed options are before, after (default), and omit"
322
+ end
315
323
  end
316
324
 
325
+
317
326
  if !['before', 'after', 'omit'].include?(@inline_list_labels)
318
327
  raise HotGlue::Error, "You passed '#{@inline_list_labels}' as the setting for --inline-list-labels but the only allowed options are before, after, and omit (default)"
319
328
  end
@@ -349,6 +358,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
349
358
 
350
359
 
351
360
  @pundit = options['pundit']
361
+ @pundit_policy_override = options['pundit_policy_override']
352
362
 
353
363
  @no_nav_menu = options['no_nav_menu']
354
364
 
@@ -651,6 +661,10 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
651
661
  @menu_file_exists = true if @nested_set.none? && File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
652
662
 
653
663
  @turbo_streams = !!options['with_turbo_streams']
664
+
665
+ puts "show only #{@show_only}"
666
+ puts "update show only #{@update_show_only}"
667
+
654
668
  end
655
669
 
656
670
  def setup_hawk_keys
@@ -966,7 +980,6 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
966
980
 
967
981
  def list_column_headings
968
982
  @template_builder.list_column_headings(
969
- col_identifier: @layout_strategy.column_classes_for_column_headings,
970
983
  column_width: @layout_strategy.column_width,
971
984
  singular: @singular
972
985
  )
@@ -1330,9 +1343,12 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
1330
1343
  append_text = " <li class='nav-item'>
1331
1344
  <%= link_to '#{@list_label_heading.humanize}', #{path_helper_plural(@nested_set.any? ? true: false)}, class: \"nav-link \#{'active' if nav == '#{plural_name}'}\" %>
1332
1345
  </li>"
1346
+ alt_append_text = " <li class='nav-item'>
1347
+ <%= link_to '#{@list_label_heading.humanize.upcase}', #{path_helper_plural(@nested_set.any? ? true: false)}, class: \"nav-link \#{'active' if nav == '#{plural_name}'}\" %>
1348
+ </li>"
1333
1349
 
1334
1350
  text = File.read(nav_file)
1335
- if text.include?(append_text)
1351
+ if text.include?(append_text) || text.include?(alt_append_text)
1336
1352
  puts "SKIPPING: Nav link for #{singular_name} already exists in #{nav_file}"
1337
1353
  else
1338
1354
  puts "APPENDING: nav link for #{singular_name} #{nav_file}"
@@ -1427,7 +1443,6 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
1427
1443
 
1428
1444
  def all_line_fields
1429
1445
  @template_builder.all_line_fields(
1430
- col_identifier: @layout_strategy.column_classes_for_line_fields,
1431
1446
  perc_width: @layout_strategy.each_col, # undefined method `each_col'
1432
1447
  layout_strategy: @layout_strategy
1433
1448
  )
@@ -1531,9 +1546,9 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
1531
1546
  if @nested_set.none?
1532
1547
  "\"\""
1533
1548
  else
1534
- @nested_set.collect { |arg|
1535
- "(((\"__#{arg[:singular]}-\#{" + "@" + arg[:singular] + ".id}\") if @" + arg[:singular] + ") || \"\")"
1536
- }.join(" + ")
1549
+ "\"" + @nested_set.collect { |arg|
1550
+ "__#{arg[:singular]}-\#{" + "@" + arg[:singular] + ".id}"
1551
+ }.join("") + "\""
1537
1552
  end
1538
1553
  end
1539
1554
 
@@ -78,11 +78,12 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
78
78
  end
79
79
 
80
80
  def index
81
- load_all_<%= plural %>
82
- <% if @search_fields %>
81
+ load_all_<%= plural %><% if @search_fields %>
83
82
  <%= @search_fields.collect{|field_name| @columns_map[field_name.to_sym].code_to_reset_match_if_search_is_blank}.compact.join(" \n") %><% end %>
84
- load_all_<%= plural %><% if @pundit %><% if @pundit %>
85
- authorize @<%= plural_name %><% end %>
83
+ <% if @pundit %><% if @pundit && !@pundit_policy_override %>
84
+ authorize @<%= plural_name %><% elsif @pundit && @pundit_policy_override %>
85
+ skip_authorization
86
+ raise Pundit::NotAuthorizedError if ! <%= @pundit_policy_override %>.index?<% end %>
86
87
  rescue Pundit::NotAuthorizedError
87
88
  flash[:alert] = 'You are not authorized to perform this action.'
88
89
  render 'layouts/error'<% end %>
@@ -92,7 +93,10 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
92
93
  @<%= singular_name %> = <%= class_name %>.new<% if eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %>(<%= @object_owner_sym %>: <%= @object_owner_eval %>)<% end %><% elsif @object_owner_optional && any_nested? %>
93
94
  @<%= singular_name %> = <%= class_name %>.new({}.merge(<%= @nested_set.last[:singular] %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}))<% else %>
94
95
  @<%= singular_name %> = <%= class_name %>.new(<% if any_nested? %><%= @object_owner_sym %>: <%= @object_owner_eval %><% end %>)<% end %>
95
- <% if @pundit %>authorize @<%= singular_name %><% end %><% if @pundit %>
96
+ <% if @pundit && !@pundit_policy_override %>
97
+ authorize @<%= singular %><% elsif @pundit && @pundit_policy_override %>
98
+ skip_authorization
99
+ raise Pundit::NotAuthorizedError if ! <%= @pundit_policy_override %>.new?<% end %><% if @pundit %>
96
100
  @action = 'new'
97
101
  rescue Pundit::NotAuthorizedError
98
102
  flash[:alert] = 'You are not authorized to perform this action.'
@@ -112,7 +116,10 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
112
116
  <%= creation_syntax %>
113
117
  <% if @pundit %><% @related_sets.each do |key, related_set| %>
114
118
  check_<%= related_set[:association_ids_method].to_s %>_permissions(modified_params, :create)<% end %><% end %>
115
- <% if @pundit %>authorize @<%= singular %><% end %>
119
+ <% if @pundit && !@pundit_policy_override %>
120
+ authorize @<%= singular %><% elsif @pundit && @pundit_policy_override %>
121
+ skip_authorization
122
+ raise Pundit::NotAuthorizedError if ! <%= @pundit_policy_override %>.create?<% end %>
116
123
  <%= @code_before_create ? "\n " + @code_before_create.gsub(";", "\n") : "" %>
117
124
  if @<%= singular_name %>.save<%= @code_after_create ? ("\n " + @code_after_create.gsub(";", "\n")) : ""%>
118
125
  flash[:notice] = "Successfully created #{@<%= singular %>.<%= display_class %>}"
@@ -148,8 +155,10 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
148
155
 
149
156
  <% end %>
150
157
  <% unless @no_edit %>
151
- def show<% if @pundit %>
152
- authorize @<%= singular %><% end %>
158
+ def show<% if @pundit && !@pundit_policy_override %>
159
+ authorize @<%= singular %><% elsif @pundit && @pundit_policy_override %>
160
+ skip_authorization
161
+ raise Pundit::NotAuthorizedError if ! <%= @pundit_policy_override %>.show?<% end %>
153
162
  redirect_to <%= HotGlue.optionalized_ternary(namespace: @namespace,
154
163
  target: @singular,
155
164
  top_level: false,
@@ -160,8 +169,10 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
160
169
  put_form: true).gsub("(#{singular}", "(@#{singular}") %>
161
170
  end
162
171
 
163
- def edit<% if @pundit %>
164
- authorize @<%= singular_name %><% end %>
172
+ def edit<% if @pundit && !@pundit_policy_override %>
173
+ authorize @<%= singular %><% elsif @pundit && @pundit_policy_override %>
174
+ skip_authorization
175
+ raise Pundit::NotAuthorizedError if ! <%= @pundit_policy_override %>.edit?<% end %>
165
176
  @action = 'edit'
166
177
  render :edit<% if @pundit %>
167
178
  rescue Pundit::NotAuthorizedError
@@ -187,15 +198,19 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
187
198
 
188
199
  <% if @hawk_keys.any? %> modified_params = hawk_params({<%= hawk_to_ruby %>}, modified_params)<% end %>
189
200
  <%= controller_attachment_orig_filename_pickup_syntax %>
190
- <% if @pundit %>
191
- if @<%= singular_name %>.attributes = modified_params
201
+ <% if @pundit && !@pundit_policy_override %>
192
202
  authorize @<%= singular_name %>
193
203
  <%= @code_before_update ? "\n " + @code_before_update.gsub(";", "\n") : "" %>
194
- @<%= singular_name %>.save
195
- <% else %>
196
- <%= @code_before_update ? "\n " + @code_before_update.gsub(";", "\n") : "" %>
204
+
197
205
  if @<%= singular_name %>.update(modified_params)
198
- <% end %>
206
+
207
+ <% elsif @pundit && @pundit_policy_override %>
208
+ skip_authorization
209
+ raise Pundit::NotAuthorizedError if ! <%= @pundit_policy_override %>.update?
210
+ if @<%= singular_name %>.update(modified_params)
211
+ <% else %>
212
+ <%= @code_before_update ? "\n " + @code_before_update.gsub(";", "\n") : "" %>
213
+ if @<%= singular_name %>.update(modified_params)<% end %>
199
214
  <%= post_action_parental_updates.compact.join("\n ") %>
200
215
  <%= @code_after_update ? "\n " + @code_after_update.gsub(";", "\n") : "" %>
201
216
  <% if @display_list_after_update %> load_all_<%= plural %><% end %>
@@ -216,11 +231,14 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
216
231
  end
217
232
 
218
233
  <% end %><% if destroy_action %> def destroy
219
- <% if @pundit %>authorize @<%= singular_name %><% end %>
234
+ <% if @pundit && !@pundit_policy_override %>
235
+ authorize @<%= singular %><% elsif @pundit && @pundit_policy_override %>
236
+ skip_authorization
237
+ raise Pundit::NotAuthorizedError if ! <%= @pundit_policy_override %>.destroy?<% end %>
220
238
  begin
221
239
  @<%=singular_name%>.destroy
222
240
  flash[:notice] = '<%= singular_name.titlecase %> successfully deleted'
223
- rescue StandardError => e
241
+ rescue ActiveRecordError => e
224
242
  flash[:alert] = '<%= singular_name.titlecase %> could not be deleted'
225
243
  end
226
244
  <%= post_action_parental_updates.join("\n ") %>
@@ -1,7 +1,8 @@
1
1
  <\% if @<%= singular %>.errors.none? %>
2
2
  <\%= turbo_stream.replace "<%= @namespace %>__<%= plural %>-list" + <%= nested_for_turbo_nested_constructor %> do %>
3
- <\%= render partial: "list", locals: {<%= plural %>: @<%= plural %>}<%= @nested_set.collect{|arg| ".merge(@" + arg[:singular] + " ? {nested_for: \"" + arg[:singular] + "-\#{@" + arg[:singular] + ".id}\"" + ", " + arg[:singular] + ": @" + arg[:singular] + "} : {})"}.join() %> \%>
4
- <\% end %>
3
+ <\%= render partial: "list", locals: {<%= plural %>: @<%= plural %><% if @nested_set.any? %>, <%= @nested_set.collect{|arg| "#{arg[:singular]}: @#{arg[:singular]}"}.join(", ") %>, nested_for: '<%= @nested_set.collect{|arg| "\"#{arg[:singular]}-\#{@#{arg[:singular]}.id}\""}.join("__") %>' <% end %> } %>
4
+
5
+ <\% end %>
5
6
  <\% end %>
6
7
  <!-- parental updated -->
7
8
  <%= turbo_parental_updates %>
@@ -15,5 +16,4 @@
15
16
  <\% end %>
16
17
  <\%= turbo_stream.replace "flash_notices" do %>
17
18
  <\%= render partial: "layouts/flash_notices", locals: {resource: @<%= singular %>} %>
18
-
19
19
  <\% end %>
@@ -8,30 +8,40 @@
8
8
  <% if @big_edit %>
9
9
  </div>
10
10
  </div>
11
+ </div>
12
+
11
13
 
12
14
 
13
15
  <% if @downnest_children.any? && @big_edit %>
14
- <hr />
15
- <% each_downnest_width = @downnest_children.count == 1 ? 33 : (53/@downnest_children.count).floor %>
16
- <% @downnest_object.each do |downnest, size| %>
17
- <div class="row">
18
- <div class="col-md-<%= @big_edit ? 12 : 6 %>">
16
+ <div class="container" data-controller="bootstrap-tabbed-nav">
17
+ <ul class="nav nav-tabs" id="<%= singular + "_downnest_portals" %>" role="tablist">
18
+ <% @downnest_object.each_with_index do |data,index| %>
19
+ <% downnest = data[0] %>
20
+ <li class="nav-item" role="presentation">
21
+ <button class="nav-link <%= "active" if index==0 %>" id="<%= downnest %>-tab" data-bs-toggle="tab" data-bs-target="#<%= downnest %>-portal" type="button" role="tab" aria-controls="home" aria-selected="true">
22
+ <%= downnest.titlecase.pluralize %>
23
+ </button>
24
+ </li>
25
+ <% end %>
26
+ </ul>
27
+
28
+ <div class="tab-content" id="myTabContent">
29
+ <% @downnest_object.each_with_index do |data, index| %>
30
+ <% downnest = data[0] %>
31
+ <div class="tab-pane fade <%= "show active" if index==0 %>" id="<%= downnest %>-portal" role="tabpanel" aria-labelledby="<%= downnest %>-tab">
19
32
  <% downnest_object = eval("#{singular_class}.reflect_on_association(:#{downnest})") %>
20
33
  <% if downnest_object.nil?; raise "no relationship for downnested portal `#{downnest}` found on `#{singular_class}`; please check relationship for has_many :#{downnest}"; end; %>
21
34
  <% downnest_class = downnest_object.class_name %>
22
35
  <% downnest_object_name = eval("#{downnest_class}.table_name") %>
23
36
  <% downnest_style = @layout_strategy.downnest_style %>
24
- <% if @downnest_shows_headings %>
25
- <h3>
26
- <%= downnest_class.titlecase.pluralize %>
27
- </h3>
28
- <% end %>
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 %> } \%>
30
37
 
31
- </div>
38
+ <\%= 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 %> } \%>
32
39
  </div>
33
40
  <% end %>
34
- <% end %>
41
+ </div>
42
+
35
43
  </div>
36
44
  <% end %>
37
45
 
46
+
47
+ <% end %>
@@ -1,5 +1,5 @@
1
1
  module HotGlue
2
2
  class Version
3
- CURRENT = '0.6.14'
3
+ CURRENT = '0.6.16'
4
4
  end
5
5
  end
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.14
4
+ version: 0.6.16
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-02-28 00:00:00.000000000 Z
11
+ date: 2025-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails