hot-glue 0.6.2 → 0.6.3
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 +2 -2
- data/README.md +112 -2
- data/app/helpers/hot_glue/controller_helper.rb +116 -12
- data/app/helpers/hot_glue_helper.rb +2 -0
- data/lib/generators/hot_glue/fields/association_field.rb +72 -0
- data/lib/generators/hot_glue/fields/boolean_field.rb +30 -0
- data/lib/generators/hot_glue/fields/date_field.rb +21 -1
- data/lib/generators/hot_glue/fields/date_time_field.rb +21 -1
- data/lib/generators/hot_glue/fields/enum_field.rb +22 -1
- data/lib/generators/hot_glue/fields/field.rb +4 -0
- data/lib/generators/hot_glue/fields/float_field.rb +12 -0
- data/lib/generators/hot_glue/fields/string_field.rb +18 -0
- data/lib/generators/hot_glue/fields/text_field.rb +20 -0
- data/lib/generators/hot_glue/fields/time_field.rb +17 -1
- data/lib/generators/hot_glue/markup_templates/erb.rb +61 -15
- data/lib/generators/hot_glue/scaffold_generator.rb +114 -14
- data/lib/generators/hot_glue/set_search_interface_install_generator.rb +26 -0
- data/lib/generators/hot_glue/templates/controller.rb.erb +31 -32
- data/lib/generators/hot_glue/templates/erb/_list.erb +5 -0
- data/lib/generators/hot_glue/templates/javascript/date_range_picker_controller.js +45 -0
- data/lib/generators/hot_glue/templates/javascript/search_form_controller.js +16 -0
- data/lib/generators/hot_glue/templates/javascript/time_range_picker_controller.js +38 -0
- data/lib/hotglue/version.rb +1 -1
- metadata +6 -2
@@ -8,19 +8,34 @@ module HotGlue
|
|
8
8
|
:inline_list_labels, :layout_object,
|
9
9
|
:columns, :col_identifier, :singular,
|
10
10
|
:form_placeholder_labels, :hawk_keys, :update_show_only,
|
11
|
-
:attachments, :show_only, :columns_map, :pundit, :related_sets
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
11
|
+
:attachments, :show_only, :columns_map, :pundit, :related_sets,
|
12
|
+
:search, :search_fields, :search_query_fields, :search_position,
|
13
|
+
:form_path, :layout_object, :search_clear_button, :search_autosearch
|
14
|
+
|
15
|
+
|
16
|
+
def initialize(singular:, singular_class: ,
|
17
|
+
layout_strategy: , magic_buttons: ,
|
18
|
+
small_buttons: , show_only: ,
|
19
|
+
ownership_field: , form_labels_position: ,
|
20
|
+
inline_list_labels: ,
|
21
|
+
form_placeholder_labels:, hawk_keys: ,
|
22
|
+
update_show_only:, attachments: , columns_map:, pundit:, related_sets:,
|
23
|
+
search:, search_fields:, search_query_fields: , search_position:,
|
24
|
+
search_clear_button:, search_autosearch:, layout_object:,
|
25
|
+
form_path: )
|
26
|
+
|
27
|
+
|
28
|
+
@form_path = form_path
|
29
|
+
@search = search
|
30
|
+
@search_fields = search_fields
|
31
|
+
@search_by_query = search_query_fields
|
32
|
+
@search_position = search_position
|
33
|
+
@layout_object = layout_object
|
21
34
|
|
22
35
|
@singular = singular
|
23
36
|
@singular_class = singular_class
|
37
|
+
@search_clear_button = search_clear_button
|
38
|
+
@search_autosearch = search_autosearch
|
24
39
|
|
25
40
|
@columns_map = columns_map
|
26
41
|
|
@@ -56,8 +71,7 @@ module HotGlue
|
|
56
71
|
}.join("\n")
|
57
72
|
end
|
58
73
|
|
59
|
-
def list_column_headings(
|
60
|
-
col_identifier: ,
|
74
|
+
def list_column_headings(col_identifier: ,
|
61
75
|
column_width:, singular: )
|
62
76
|
col_style = @layout_strategy.column_headings_col_style
|
63
77
|
|
@@ -74,8 +88,41 @@ module HotGlue
|
|
74
88
|
# THE FORM
|
75
89
|
################################################################
|
76
90
|
|
91
|
+
def search_input_area
|
92
|
+
columns = layout_object[:columns][:container]
|
93
|
+
column_classes = layout_strategy.column_classes_for_form_fields
|
94
|
+
|
95
|
+
|
96
|
+
res =+ "<\%= form_with url: #{form_path}, method: :get, html: {'data-turbo-action': 'advance', 'data-controller': 'search-form'} do |f| %>"
|
97
|
+
res << "<div class=\"#{@layout_strategy.row_classes} search--#{@plural}\">"
|
77
98
|
|
78
|
-
|
99
|
+
res << columns.map{ |column|
|
100
|
+
" <div class='#{column_classes} search-cell--#{singular}--#{column.join("-")}' >" +
|
101
|
+
|
102
|
+
column.map { |col|
|
103
|
+
label_class = columns_map[col].label_class
|
104
|
+
label_for = columns_map[col].label_for
|
105
|
+
the_label = "\n<label class='#{label_class}' for='search-#{label_for}'>#{col.to_s.humanize}</label>"
|
106
|
+
search_field_result = columns_map[col].search_field_output
|
107
|
+
|
108
|
+
add_spaces_each_line( "\n <span class='' >\n" +
|
109
|
+
add_spaces_each_line( (form_labels_position == 'before' ? the_label || "" : "") +
|
110
|
+
+ " <br />\n" + search_field_result +
|
111
|
+
(form_labels_position == 'after' ? the_label : "") , 4) +
|
112
|
+
"\n </span>\n <br /></div>", 2)
|
113
|
+
}.join("\n")
|
114
|
+
}.join("\n")
|
115
|
+
res << "<div class='#{column_classes}'>"
|
116
|
+
if @search_clear_button
|
117
|
+
res << "<\%= f.button \"Clear\", name: nil, 'data-search-form-target': 'clearButton', class: 'btn btn-sm btn-secondary' %>"
|
118
|
+
end
|
119
|
+
res << "<\%= submit_tag \"Search\", name: nil, class: 'btn btn-sm btn-primary' %>"
|
120
|
+
res << "</div><\% end %>"
|
121
|
+
res
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
def all_form_fields(layout_strategy:)
|
79
126
|
column_classes = layout_strategy.column_classes_for_form_fields
|
80
127
|
columns = layout_object[:columns][:container]
|
81
128
|
|
@@ -105,7 +152,7 @@ module HotGlue
|
|
105
152
|
else
|
106
153
|
columns_map[col].form_field_output
|
107
154
|
end
|
108
|
-
|
155
|
+
|
109
156
|
@tinymce_stimulus_controller = (columns_map[col].modify_as == {tinymce: 1} ? "data-controller='tiny-mce' " : "")
|
110
157
|
|
111
158
|
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" +
|
@@ -133,7 +180,6 @@ module HotGlue
|
|
133
180
|
################################################################
|
134
181
|
|
135
182
|
def all_line_fields(layout_strategy:,
|
136
|
-
layout_object: ,
|
137
183
|
perc_width:,
|
138
184
|
col_identifier: nil)
|
139
185
|
|
@@ -23,7 +23,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
23
23
|
:nest_with, :path, :plural, :sample_file_path, :show_only_data, :singular,
|
24
24
|
:singular_class, :smart_layout, :stacked_downnesting, :update_show_only, :ownership_field,
|
25
25
|
:layout_strategy, :form_placeholder_labels, :form_labels_position, :pundit,
|
26
|
-
:self_auth, :namespace_value, :related_sets
|
26
|
+
:self_auth, :namespace_value, :related_sets, :search_clear_button, :search_autosearch
|
27
27
|
# important: using an attr_accessor called :namespace indirectly causes a conflict with Rails class_name method
|
28
28
|
# so we use namespace_value instead
|
29
29
|
|
@@ -48,7 +48,6 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
48
48
|
class_option :no_edit, type: :boolean, default: false
|
49
49
|
class_option :no_list, type: :boolean, default: false
|
50
50
|
class_option :no_controller, type: :boolean, default: false
|
51
|
-
class_option :no_list, type: :boolean, default: false
|
52
51
|
class_option :no_paginate, type: :boolean, default: false
|
53
52
|
class_option :paginate_per_page_selector, type: :boolean, default: false
|
54
53
|
class_option :big_edit, type: :boolean, default: false
|
@@ -95,6 +94,24 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
95
94
|
class_option :code_before_update, default: nil
|
96
95
|
class_option :code_after_update, default: nil
|
97
96
|
|
97
|
+
class_option :search, default: nil # set or predicate
|
98
|
+
|
99
|
+
# FOR THE SET SEARCH
|
100
|
+
class_option :search_fields, default: nil # comma separated list of all fields to search
|
101
|
+
|
102
|
+
# for the single-entry search box, they will be removed from the list specified above.
|
103
|
+
class_option :search_query_fields, default: '' # comma separated list of fields to search by single-entry search term
|
104
|
+
class_option :search_position, default: 'vertical' # choices are vertical or horizontal
|
105
|
+
|
106
|
+
|
107
|
+
class_option :search_clear_button, default: false
|
108
|
+
class_option :saerch_autosearch, default: false
|
109
|
+
|
110
|
+
|
111
|
+
# FOR THE PREDICATE SEARCH
|
112
|
+
# TDB
|
113
|
+
|
114
|
+
|
98
115
|
def initialize(*meta_args)
|
99
116
|
super
|
100
117
|
|
@@ -295,6 +312,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
295
312
|
|
296
313
|
@no_edit = options['no_edit'] || false
|
297
314
|
@no_list = options['no_list'] || false
|
315
|
+
|
298
316
|
@no_controller = options['no_controller'] || false
|
299
317
|
@no_list = options['no_list'] || false
|
300
318
|
@no_list_label = options['no_list_label'] || false
|
@@ -471,6 +489,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
471
489
|
@columns_map[col] = this_column_object.field
|
472
490
|
end
|
473
491
|
|
492
|
+
|
474
493
|
@columns_map.each do |key, field|
|
475
494
|
if field.is_a?(AssociationField)
|
476
495
|
if @modify_as && @modify_as[key] && @modify_as[key][:typeahead]
|
@@ -490,11 +509,42 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
490
509
|
end
|
491
510
|
end
|
492
511
|
|
512
|
+
# search
|
513
|
+
@search = options['search']
|
514
|
+
if @search == 'set'
|
515
|
+
@search_fields = options['search_fields'].split(',') || @columns
|
516
|
+
# within the set search we will take out any fields on the query list
|
517
|
+
# or the field
|
518
|
+
@search_query_fields = options['search_query_fields'].split(',') || []
|
519
|
+
@search_position = options['search_position'] || 'vertical'
|
520
|
+
|
521
|
+
@search_fields = @search_fields - @search_query_fields
|
522
|
+
|
523
|
+
@search_fields.each do |field|
|
524
|
+
if !@columns.include?(field.to_sym)
|
525
|
+
raise "You specified a search field for #{field} but that field is not in the list of columns"
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
@search_clear_button = !!options['search_clear_button']
|
530
|
+
@search_autosearch = !!options['search_autosearch']
|
531
|
+
|
532
|
+
elsif @search == 'predicate'
|
533
|
+
|
534
|
+
end
|
535
|
+
|
536
|
+
builder = HotGlue::Layout::Builder.new(generator: self,
|
537
|
+
include_setting: options['include'],
|
538
|
+
buttons_width: buttons_width)
|
539
|
+
@layout_object = builder.construct
|
493
540
|
|
494
541
|
|
495
542
|
# create the template object
|
543
|
+
|
544
|
+
|
496
545
|
if @markup == "erb"
|
497
546
|
@template_builder = HotGlue::ErbTemplate.new(
|
547
|
+
layout_object: @layout_object,
|
498
548
|
layout_strategy: @layout_strategy,
|
499
549
|
magic_buttons: @magic_buttons,
|
500
550
|
small_buttons: @small_buttons,
|
@@ -510,7 +560,14 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
510
560
|
attachments: @attachments,
|
511
561
|
columns_map: @columns_map,
|
512
562
|
pundit: @pundit,
|
513
|
-
related_sets: @related_sets
|
563
|
+
related_sets: @related_sets,
|
564
|
+
search: @search,
|
565
|
+
search_fields: @search_fields,
|
566
|
+
search_query_fields: @search_query_fields,
|
567
|
+
search_position: @search_position,
|
568
|
+
search_clear_button: @search_clear_button,
|
569
|
+
search_autosearch: @search_autosearch,
|
570
|
+
form_path: form_path_new_helper
|
514
571
|
)
|
515
572
|
elsif @markup == "slim"
|
516
573
|
raise(HotGlue::Error, "SLIM IS NOT IMPLEMENTED")
|
@@ -518,10 +575,6 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
518
575
|
raise(HotGlue::Error, "HAML IS NOT IMPLEMENTED")
|
519
576
|
end
|
520
577
|
|
521
|
-
builder = HotGlue::Layout::Builder.new(generator: self,
|
522
|
-
include_setting: options['include'],
|
523
|
-
buttons_width: buttons_width)
|
524
|
-
@layout_object = builder.construct
|
525
578
|
|
526
579
|
@menu_file_exists = true if @nested_set.none? && File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
|
527
580
|
|
@@ -688,6 +741,9 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
688
741
|
@columns = @the_object.columns.map(&:name).map(&:to_sym).reject { |field| !@include_fields.include?(field) }
|
689
742
|
end
|
690
743
|
|
744
|
+
|
745
|
+
@columns = @columns -@nested_set.collect { |set| (set[:singular] + "_id").to_sym }
|
746
|
+
|
691
747
|
if @attachments.any?
|
692
748
|
puts "Adding attachments-as-columns: #{@attachments}"
|
693
749
|
@attachments.keys.each do |attachment|
|
@@ -826,7 +882,6 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
826
882
|
|
827
883
|
def list_column_headings
|
828
884
|
@template_builder.list_column_headings(
|
829
|
-
layout_object: @layout_object,
|
830
885
|
col_identifier: @layout_strategy.column_classes_for_column_headings,
|
831
886
|
column_width: @layout_strategy.column_width,
|
832
887
|
singular: @singular
|
@@ -1252,8 +1307,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1252
1307
|
end
|
1253
1308
|
|
1254
1309
|
def form_fields_html
|
1255
|
-
@template_builder.all_form_fields(layout_strategy: @layout_strategy
|
1256
|
-
layout_object: @layout_object)
|
1310
|
+
@template_builder.all_form_fields(layout_strategy: @layout_strategy)
|
1257
1311
|
end
|
1258
1312
|
|
1259
1313
|
def list_label
|
@@ -1268,8 +1322,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1268
1322
|
@template_builder.all_line_fields(
|
1269
1323
|
col_identifier: @layout_strategy.column_classes_for_line_fields,
|
1270
1324
|
perc_width: @layout_strategy.each_col, # undefined method `each_col'
|
1271
|
-
layout_strategy: @layout_strategy
|
1272
|
-
layout_object: @layout_object
|
1325
|
+
layout_strategy: @layout_strategy
|
1273
1326
|
)
|
1274
1327
|
end
|
1275
1328
|
|
@@ -1387,8 +1440,55 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1387
1440
|
end
|
1388
1441
|
end
|
1389
1442
|
|
1443
|
+
|
1444
|
+
def load_all_code
|
1445
|
+
# the inner method definition of the load_all_* method
|
1446
|
+
res = +""
|
1447
|
+
if @search_fields
|
1448
|
+
res << @search_fields.collect{ |field|
|
1449
|
+
if !@columns_map[field.to_sym].load_all_query_statement.empty?
|
1450
|
+
@columns_map[field.to_sym].load_all_query_statement
|
1451
|
+
end
|
1452
|
+
}.compact.join("\n" + spaces(4))
|
1453
|
+
res << "\n"
|
1454
|
+
end
|
1455
|
+
|
1456
|
+
if pundit
|
1457
|
+
res << "@#{ plural_name } = policy_scope(#{ object_scope }).page(params[:page])#{ n_plus_one_includes }#{ ".per(per)" if @paginate_per_page_selector }"
|
1458
|
+
else
|
1459
|
+
if !@self_auth
|
1460
|
+
res << spaces(4) + "@#{ plural_name } = #{ object_scope.gsub("@",'') }#{ n_plus_one_includes }.page(params[:page])#{ ".per(per)" if @paginate_per_page_selector }"
|
1461
|
+
if @search_fields
|
1462
|
+
res << @search_fields.collect{ |field|
|
1463
|
+
wqs = @columns_map[field.to_sym].where_query_statement
|
1464
|
+
if !wqs.empty?
|
1465
|
+
"\n" + spaces(4) + "@#{ plural_name } = @#{ plural_name }#{ wqs } if #{field}_query"
|
1466
|
+
end
|
1467
|
+
}.compact.join
|
1468
|
+
end
|
1469
|
+
elsif @nested_set[0] && @nested_set[0][:optional]
|
1470
|
+
res << "@#{ plural_name } = #{ class_name }.all"
|
1471
|
+
else
|
1472
|
+
res << "@#{ plural_name } = #{ class_name }.where(id: #{ auth_object.gsub("@",'') }.id)#{ n_plus_one_includes }"
|
1473
|
+
if @search_fields
|
1474
|
+
res << @search_fields.collect{ |field|
|
1475
|
+
@columns_map[field.to_sym].where_query_statement
|
1476
|
+
}.join("\n")
|
1477
|
+
end
|
1478
|
+
res << ".page(params[:page])#{ ".per(per)" if @paginate_per_page_selector }"
|
1479
|
+
end
|
1480
|
+
end
|
1481
|
+
res
|
1482
|
+
end
|
1483
|
+
|
1484
|
+
|
1390
1485
|
private # thor does something fancy like sending the class all of its own methods during some strange run sequence
|
1391
1486
|
# does not like public methods
|
1487
|
+
|
1488
|
+
def spaces(num)
|
1489
|
+
" " * num
|
1490
|
+
end
|
1491
|
+
|
1392
1492
|
def cc_filename_with_extensions(name, file_format = format)
|
1393
1493
|
[name, file_format].compact.join(".")
|
1394
1494
|
end
|
@@ -1419,8 +1519,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1419
1519
|
|
1420
1520
|
def turbo_parental_updates
|
1421
1521
|
@nested_set.collect { |data|
|
1422
|
-
"<%= turbo_stream.replace \"#{@namespace
|
1423
|
-
<%= render partial: \"#{@namespace}/#{data[:plural]}/
|
1522
|
+
"<%= turbo_stream.replace \"__#{@namespace if @namespace}\#{dom_id(@#{data[:singular]})}\" do %>
|
1523
|
+
<%= render partial: \"#{@namespace}/#{data[:plural]}/line\", locals: {#{data[:singular]}: @#{singular}.#{data[:singular]}.reload} %>
|
1424
1524
|
<% end %>"
|
1425
1525
|
}.join("\n")
|
1426
1526
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module HotGlue
|
4
|
+
class SetSearchInterfaceInstallGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('templates', __dir__)
|
6
|
+
|
7
|
+
def filepath_prefix
|
8
|
+
# todo: inject the context
|
9
|
+
'spec/dummy/' if $INTERNAL_SPECS
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(*args) #:nodoc:
|
13
|
+
super
|
14
|
+
|
15
|
+
['date_range_picker','time_range_picker','search_form'].each do |file|
|
16
|
+
system("./bin/rails generate stimulus #{file.titlecase.gsub(" ", "")}")
|
17
|
+
copy_file "javascript/#{file}_controller.js", "#{filepath_prefix}app/javascript/controllers/#{file}.js"
|
18
|
+
puts "HOT GLUE --> copying #{file} stimulus controller into app/javascript/controllers/#{file}.js"
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
|
@@ -70,24 +70,21 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
70
70
|
end<% end %>
|
71
71
|
<% if @paginate_per_page_selector %>def per
|
72
72
|
params[:per] || 10
|
73
|
+
end<% end %>
|
74
|
+
<% unless @no_list %>
|
75
|
+
def load_all_<%= plural %>
|
76
|
+
<%= load_all_code %>
|
73
77
|
end
|
74
78
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
@<%= plural_name %> = <%= object_scope.gsub("@",'') %><%= n_plus_one_includes %>.page(params[:page])<%= ".per(per)" if @paginate_per_page_selector %><%= " if params.include?(:#{ @nested_set.last[:singular]}_id)" if @nested_set.any? && @nested_set[0] && @nested_set[0][:optional] %><% if @nested_set[0] && @nested_set[0][:optional] %>
|
79
|
-
@<%= plural_name %> = <%= class_name %>.all<% end %><% else %>
|
80
|
-
@<%= plural_name %> = <%= class_name %>.where(id: <%= auth_object.gsub("@",'') %>.id)<%= n_plus_one_includes %>.page(params[:page])<%= ".per(per)" if @paginate_per_page_selector %><% end %>
|
81
|
-
<% end %>
|
82
|
-
end
|
83
|
-
|
84
|
-
def index
|
79
|
+
def index <% if @search == "set" %>
|
80
|
+
@q = params[:q] || <%= {"0" => @search_fields.collect{|foo| {"#{foo}_match".to_sym => "", "#{foo}_search".to_sym => ""}}.reduce({}, :merge) } %> <% end %><% if @search_fields %>
|
81
|
+
<%= @search_fields.collect{|field_name| @columns_map[field_name.to_sym].code_to_reset_match_if_search_is_blank}.compact.join(" \n") %><% end %>
|
85
82
|
load_all_<%= plural %><% if @pundit %><% if @pundit %>
|
86
83
|
authorize @<%= plural_name %><% end %>
|
87
84
|
rescue Pundit::NotAuthorizedError
|
88
85
|
flash[:alert] = 'You are not authorized to perform this action.'
|
89
86
|
render 'layouts/error'<% end %>
|
90
|
-
end
|
87
|
+
end<% end %>
|
91
88
|
|
92
89
|
<% if create_action %> def new<% if @object_owner_sym %>
|
93
90
|
@<%= singular_name %> = <% if @pundit %>policy_scope(<% end %><%= class_name %><% if @pundit %>)<% end %>.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? %>
|
@@ -102,10 +99,11 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
102
99
|
end
|
103
100
|
|
104
101
|
def create
|
105
|
-
|
102
|
+
flash[:alert] = +''
|
103
|
+
flash[:notice] = +''
|
104
|
+
modified_params = modify_date_inputs_on_params(<%= singular_name %>_params.dup, <%= current_user_object %>, <%= datetime_fields_list %>)<% if @object_owner_sym && eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %>
|
106
105
|
modified_params = modified_params.merge(<%= @object_owner_sym %>: <%= @object_owner_eval %>) <% elsif @object_owner_optional && any_nested? %>
|
107
|
-
modified_params = modified_params.merge(<%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}) <%
|
108
|
-
modified_params = modified_params.merge(<%= @object_owner_eval %>) <% end %>
|
106
|
+
modified_params = modified_params.merge(<%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}) <% end %>
|
109
107
|
|
110
108
|
<% if @hawk_keys.any? %>
|
111
109
|
modified_params = hawk_params({<%= hawk_to_ruby %>}, modified_params)<% end %>
|
@@ -125,11 +123,9 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
125
123
|
@action = 'new'
|
126
124
|
render :create, status: :unprocessable_entity
|
127
125
|
end<% if @pundit %>
|
128
|
-
rescue Pundit::NotAuthorizedError
|
129
|
-
|
130
|
-
|
131
|
-
flash[:alert] << flash[:notice]
|
132
|
-
render :index <% end %>
|
126
|
+
rescue Pundit::NotAuthorizedError => e
|
127
|
+
@user.errors.add(:base, e.message)
|
128
|
+
render :create, status: :unprocessable_entity<% end %>
|
133
129
|
end
|
134
130
|
|
135
131
|
<% end %>
|
@@ -165,8 +161,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
165
161
|
|
166
162
|
modified_params = modify_date_inputs_on_params(<% if @update_show_only %>update_<% end %><%= singular_name %>_params.dup<%= controller_update_params_tap_away_magic_buttons %>, <%= current_user_object %>, <%= datetime_fields_list %>) <% if @object_owner_sym && eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %>
|
167
163
|
modified_params = modified_params.merge(<%= @object_owner_sym %>: <%= @object_owner_eval %>) <% elsif @object_owner_optional && any_nested? %>
|
168
|
-
modified_params = modified_params.merge(<%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}) <%
|
169
|
-
modified_params = modified_params.merge(<%= @object_owner_eval %>) <% end %>
|
164
|
+
modified_params = modified_params.merge(<%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}) <% end %>
|
170
165
|
<% if @pundit %><% @related_sets.each do |key, related_set| %>
|
171
166
|
check_<%= related_set[:association_ids_method].to_s %>_permissions(modified_params, :update)<% end %><% end %>
|
172
167
|
|
@@ -212,27 +207,31 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
212
207
|
|
213
208
|
<% if @pundit %><% @related_sets.each do |key, rs| %>
|
214
209
|
def check_<%= rs[:association_ids_method] %>_permissions(modified_params, action)
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
raise Pundit::NotAuthorizedError, message: @<%= singular %>.errors.collect{|k| "#{k.attribute} #{k.message}"}.join(" ")
|
224
|
-
end
|
225
|
-
end
|
210
|
+
# authorize the <%= rs[:association_ids_method] %> change using special modified_relations: {
|
211
|
+
# <%= rs[:association_ids_method] %>: modified_params[:<%= rs[:association_ids_method] %>>]} syntax for Pundit
|
212
|
+
modified_relations = { <%= rs[:association_ids_method] %>: modified_params[:<%= rs[:association_ids_method] %>] }
|
213
|
+
return unless modified_params[:<%= rs[:association_ids_method] %>].present?
|
214
|
+
policy_check = <%= singular_class %>Policy.new(current_user, @<%= singular %>,
|
215
|
+
modified_relations:).method("#{action}?".to_sym).call
|
216
|
+
return if policy_check
|
217
|
+
raise Pundit::NotAuthorizedError, message: @<%= singular %>.errors.collect{|k| "#{k.attribute} #{k.message}"}.join(" ")
|
226
218
|
end<% end %><% end %>
|
227
219
|
|
228
220
|
def <%=singular_name%>_params
|
229
221
|
params.require(:<%= testing_name %>).permit(<%= ((fields_filtered_for_strong_params - @show_only ) + @magic_buttons.collect{|x| "__#{x}"}).collect{|sym| ":#{sym}"}.join(", ") %><%= ", " + @related_sets.collect{|key, rs| "#{rs[:association_ids_method]}: []"}.join(", ") if @related_sets.any? %>)
|
230
222
|
end<% if @update_show_only %>
|
231
223
|
|
224
|
+
<% unless @no_edit %>
|
232
225
|
def update_<%=singular_name%>_params
|
233
226
|
params.require(:<%= testing_name %>).permit(<%= ((fields_filtered_for_strong_params - @update_show_only) + @magic_buttons.collect{|x| "__#{x}"}).collect{|sym| ":#{sym}"}.join(", ") %><%= ", " + @related_sets.collect{|key, rs| "#{rs[:association_ids_method]}: []"}.join(", ") if @related_sets.any? %>)
|
234
227
|
end<% end %>
|
228
|
+
<% end %>
|
235
229
|
|
230
|
+
<% if @search %>
|
231
|
+
def search_params
|
232
|
+
params.permit(:q, :page)
|
233
|
+
end
|
234
|
+
<% end %>
|
236
235
|
def namespace
|
237
236
|
<% if @namespace %>'<%= @namespace %>/'<% else %><% end %>
|
238
237
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
<\%= turbo_frame_tag "<%= @namespace %>__<%= plural %>-list" <%= nested_for_turbo_id_list_constructor %> do %>
|
2
|
+
|
2
3
|
<div class="<%= @container_name %> <%= @layout_strategy.list_classes %>">
|
3
4
|
<% unless @no_list || @no_list_label || (@nested_set.any? && !@nested_set.collect{|x| x[:optional]}.any?) %>
|
4
5
|
<% unless list_label.nil? %><h4>
|
@@ -40,6 +41,10 @@
|
|
40
41
|
</div>
|
41
42
|
<% end %>
|
42
43
|
|
44
|
+
<% if @search %>
|
45
|
+
<%= @template_builder.search_input_area %>
|
46
|
+
<% end %>
|
47
|
+
|
43
48
|
<\% if <%= plural %>.empty? %>
|
44
49
|
<div>
|
45
50
|
None
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
// Connects to data-controller="date-range-picker"
|
4
|
+
export default class extends Controller {
|
5
|
+
|
6
|
+
static targets = [ "matchSelector", "start", "end" ];
|
7
|
+
connect() {
|
8
|
+
|
9
|
+
console.log("date_range_picker_controller.js connect.....")
|
10
|
+
}
|
11
|
+
|
12
|
+
matchSelection(event) {
|
13
|
+
|
14
|
+
console.log("date_range_picker_controller.js matchSelection.....")
|
15
|
+
console.log(event.target.value)
|
16
|
+
// this.matchSelectorTarget.value = event.target.value
|
17
|
+
|
18
|
+
switch(event.target.value) {
|
19
|
+
case "is_on":
|
20
|
+
this.startTarget.disabled = false
|
21
|
+
this.endTarget.disabled = true
|
22
|
+
this.endTarget.value = ""
|
23
|
+
break;
|
24
|
+
case "is_between":
|
25
|
+
this.startTarget.disabled = false
|
26
|
+
this.endTarget.disabled = false
|
27
|
+
break;
|
28
|
+
case "is_on_or_after":
|
29
|
+
this.startTarget.disabled = false
|
30
|
+
this.endTarget.disabled = true
|
31
|
+
this.endTarget.value = ""
|
32
|
+
break;
|
33
|
+
case "is_before_or_on":
|
34
|
+
this.startTarget.disabled = true
|
35
|
+
this.startTarget.value = ""
|
36
|
+
this.endTarget.disabled = false
|
37
|
+
break;
|
38
|
+
case "not_on":
|
39
|
+
this.startTarget.disabled = false
|
40
|
+
this.endTarget.disabled = true
|
41
|
+
this.endTarget.value = ""
|
42
|
+
break;
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
// Connects to data-controller="search_form"
|
4
|
+
export default class extends Controller {
|
5
|
+
static targets = ["clearButton"];
|
6
|
+
|
7
|
+
connect() {
|
8
|
+
|
9
|
+
if (this.hasClearButtonTarget) {
|
10
|
+
this.clearButtonTarget.addEventListener("click", (event) => {
|
11
|
+
event.preventDefault()
|
12
|
+
this.element.reset()
|
13
|
+
})
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
// Connects to data-controller="time-range-picker"
|
4
|
+
export default class extends Controller {
|
5
|
+
static targets = [ "matchSelector", "start", "end" ];
|
6
|
+
connect() {
|
7
|
+
console.log("time_range_picker_controller.js connect.....")
|
8
|
+
}
|
9
|
+
|
10
|
+
matchSelection(event) {
|
11
|
+
|
12
|
+
console.log("time_range_picker_controller.js matchSelection.....")
|
13
|
+
console.log(event.target.value)
|
14
|
+
// this.matchSelectorTarget.value = event.target.value
|
15
|
+
|
16
|
+
switch(event.target.value) {
|
17
|
+
case "is_at":
|
18
|
+
this.startTarget.disabled = false
|
19
|
+
this.endTarget.disabled = true
|
20
|
+
this.endTarget.value = ""
|
21
|
+
break;
|
22
|
+
case "is_between":
|
23
|
+
this.startTarget.disabled = false
|
24
|
+
this.endTarget.disabled = false
|
25
|
+
break;
|
26
|
+
case "is_at_or_after":
|
27
|
+
this.startTarget.disabled = false
|
28
|
+
this.endTarget.disabled = true
|
29
|
+
this.endTarget.value = ""
|
30
|
+
break;
|
31
|
+
case "is_before_or_at":
|
32
|
+
this.startTarget.disabled = true
|
33
|
+
this.startTarget.value = ""
|
34
|
+
this.endTarget.disabled = false
|
35
|
+
break;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
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.3
|
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:
|
11
|
+
date: 2024-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- lib/generators/hot_glue/markup_templates/erb.rb
|
108
108
|
- lib/generators/hot_glue/nav_template_generator.rb
|
109
109
|
- lib/generators/hot_glue/scaffold_generator.rb
|
110
|
+
- lib/generators/hot_glue/set_search_interface_install_generator.rb
|
110
111
|
- lib/generators/hot_glue/templates/base_controller.rb.erb
|
111
112
|
- lib/generators/hot_glue/templates/capybara_login.rb
|
112
113
|
- lib/generators/hot_glue/templates/computer_code.jpg
|
@@ -127,7 +128,10 @@ files:
|
|
127
128
|
- lib/generators/hot_glue/templates/erb/index.erb
|
128
129
|
- lib/generators/hot_glue/templates/erb/new.erb
|
129
130
|
- lib/generators/hot_glue/templates/erb/update.turbo_stream.erb
|
131
|
+
- lib/generators/hot_glue/templates/javascript/date_range_picker_controller.js
|
130
132
|
- lib/generators/hot_glue/templates/javascript/dropzone_controller.js
|
133
|
+
- lib/generators/hot_glue/templates/javascript/search_form_controller.js
|
134
|
+
- lib/generators/hot_glue/templates/javascript/time_range_picker_controller.js
|
131
135
|
- lib/generators/hot_glue/templates/system_spec.rb.erb
|
132
136
|
- lib/generators/hot_glue/templates/themes/hotglue_scaffold_dark_knight.scss
|
133
137
|
- lib/generators/hot_glue/templates/themes/hotglue_scaffold_like_bootstrap.scss
|