hot-glue 0.6.2 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|