hot-glue 0.6.1 → 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/.github/FUNDING.yml +1 -1
- data/Gemfile.lock +2 -2
- data/README.md +193 -14
- 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 +73 -2
- 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 +139 -16
- data/lib/generators/hot_glue/set_search_interface_install_generator.rb +26 -0
- data/lib/generators/hot_glue/templates/controller.rb.erb +50 -39
- data/lib/generators/hot_glue/templates/erb/_edit.erb +3 -1
- data/lib/generators/hot_glue/templates/erb/_list.erb +5 -0
- data/lib/generators/hot_glue/templates/erb/_new_form.erb +4 -1
- 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/generators/hot_glue/templates/typeahead_controller.rb.erb +1 -0
- data/lib/generators/hot_glue/typeahead_generator.rb +5 -1
- data/lib/hotglue/version.rb +1 -1
- metadata +7 -3
@@ -34,7 +34,7 @@ class DateTimeField < Field
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def form_field_output
|
37
|
-
"<%= datetime_field_localized(f, :#{name}, #{singular}.#{name}, '#{ name.to_s.humanize }') %>"
|
37
|
+
"<%= datetime_field_localized(f, :#{name}, #{singular}.#{name}, label: '#{ name.to_s.humanize }' ) %>"
|
38
38
|
end
|
39
39
|
|
40
40
|
def viewable_output
|
@@ -48,4 +48,24 @@ class DateTimeField < Field
|
|
48
48
|
<% end %>"
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
def search_field_output
|
53
|
+
" <div data-controller='date-range-picker' >"+
|
54
|
+
"\n <%= f.select 'q[0][#{name}_match]', options_for_select([['', ''], ['is on', 'is_on'], " +
|
55
|
+
"\n ['is between', 'is_between'], ['is on or after', 'is_on_or_after'], " +
|
56
|
+
"\n ['is before or on', 'is_before_or_on'], ['not on', 'not_on']], @q[\'0\']['#{name}_match'] ), {} ," +
|
57
|
+
"\n { class: 'form-control match', 'data-action': 'change->date-range-picker#matchSelection' } %>"+
|
58
|
+
"\n <%= datetime_local_field 'q[0]', '#{name}_search_start', {value: @q[\'0\'][:#{name}_search_start], autocomplete: 'off', size: 40, class: 'form-control', placeholder: 'start', 'data-date-range-picker-target': 'start' } %>" +
|
59
|
+
"\n <%= datetime_local_field 'q[0]', '#{name}_search_end', {value: @q[\'0\'][:#{name}_search_end], autocomplete: 'off', size: 40, class: 'form-control', placeholder: 'end' , 'data-date-range-picker-target': 'end' } %>" +
|
60
|
+
"\n </div>"
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def where_query_statement
|
65
|
+
".where(*#{name}_query)"
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_all_query_statement
|
69
|
+
"#{name}_query = date_query_constructor(:#{name}, @q['0'][:#{name}_match], @q['0'][:#{name}_search_start], @q['0'][:#{name}_search_end])"
|
70
|
+
end
|
51
71
|
end
|
@@ -38,7 +38,7 @@ class EnumField < Field
|
|
38
38
|
enum_definer = "#{class_name}.defined_enums['#{name}']"
|
39
39
|
end
|
40
40
|
|
41
|
-
res = "<%= f.collection_select(:#{name}, enum_to_collection_select(#{enum_definer}), :key, :value, {selected: #{singular}.#{name} }, class: 'form-control') %>"
|
41
|
+
res = "<%= f.collection_select(:#{name}, enum_to_collection_select(#{enum_definer}), :key, :value, {include_blank: true, selected: #{singular}.#{name} }, class: 'form-control') %>"
|
42
42
|
|
43
43
|
|
44
44
|
if modify_as && modify_as[:enum] == :partials
|
@@ -79,4 +79,25 @@ class EnumField < Field
|
|
79
79
|
def form_show_only_output
|
80
80
|
viewable_output
|
81
81
|
end
|
82
|
+
|
83
|
+
|
84
|
+
def search_field_output
|
85
|
+
enum_type = eval("#{class_name}.columns.select{|x| x.name == '#{name}'}[0].sql_type")
|
86
|
+
if eval("defined? #{class_name}.#{enum_type}_labels") == "method"
|
87
|
+
enum_definer = "#{class_name}.#{enum_type}_labels"
|
88
|
+
else
|
89
|
+
enum_definer = "#{class_name}.defined_enums['#{name}']"
|
90
|
+
end
|
91
|
+
|
92
|
+
"<%= f.collection_select(\'q[0][#{name}_search]\', enum_to_collection_select(#{enum_definer}), :key, :value, {include_blank: true, selected: @q['0']['#{name}_search'] }, class: 'form-control') %>"
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def where_query_statement
|
97
|
+
".where(*#{name}_query)"
|
98
|
+
end
|
99
|
+
|
100
|
+
def load_all_query_statement
|
101
|
+
"#{name}_query = enum_constructor(:#{name}, @q['0'][:#{name}_search])"
|
102
|
+
end
|
82
103
|
end
|
@@ -47,4 +47,22 @@ class StringField < Field
|
|
47
47
|
text_area_output( 65536)
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
def search_field_output
|
52
|
+
"<%= f.select 'q[0][#{name}_match]', options_for_select([['', ''], ['contains', 'contains'], ['is exactly', 'is_exactly'], ['starts with', 'starts_with'], ['ends with', 'ends_with']], @q[\'0\']['#{name}_match'] ), {} , { class: 'form-control match' } %>"+
|
53
|
+
"<%= f.text_field 'q[0][#{name}_search]', value: @q[\'0\'][:#{name}_search], autocomplete: 'off', size: 40, class: 'form-control', type: 'text' %>"
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def where_query_statement
|
58
|
+
".where('#{name} ILIKE ?', #{name}_query)"
|
59
|
+
end
|
60
|
+
|
61
|
+
def load_all_query_statement
|
62
|
+
"#{name}_query = string_query_constructor(@q['0'][:#{name}_match], @q['0'][:#{name}_search])"
|
63
|
+
end
|
64
|
+
|
65
|
+
def code_to_reset_match_if_search_is_blank
|
66
|
+
" @q['0'][:#{name}_match] = '' if @q['0'][:#{name}_search] == ''"
|
67
|
+
end
|
50
68
|
end
|
@@ -28,4 +28,24 @@ class TextField < Field
|
|
28
28
|
text_area_output( 65536)
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
|
33
|
+
def search_field_output
|
34
|
+
"<%= f.select 'q[0][#{name}_match]', options_for_select([['', ''], ['contains', 'contains'], ['is exactly', 'is_exactly'], ['starts with', 'starts_with'], ['ends with', 'ends_with']], @q[\'0\']['#{name}_match'] ), {} , { class: 'form-control match' } %>"+
|
35
|
+
"<%= f.text_field 'q[0][#{name}_search]', value: @q[\'0\'][:#{name}_search], autocomplete: 'off', size: 40, class: 'form-control', type: 'text' %>"
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def where_query_statement
|
40
|
+
".where('#{name} ILIKE ?', #{name}_query)"
|
41
|
+
end
|
42
|
+
|
43
|
+
def load_all_query_statement
|
44
|
+
"#{name}_query = string_query_constructor(@q['0'][:#{name}_match], @q['0'][:#{name}_search])"
|
45
|
+
end
|
46
|
+
|
47
|
+
def code_to_reset_match_if_search_is_blank
|
48
|
+
" @q['0'][:#{name}_match] = '' if @q['0'][:#{name}_search] == ''"
|
49
|
+
end
|
50
|
+
|
31
51
|
end
|
@@ -5,7 +5,7 @@ class TimeField < Field
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def form_field_output
|
8
|
-
"<%= time_field_localized(f, :#{name}, #{singular}.#{name},
|
8
|
+
"<%= time_field_localized(f, :#{name}, #{singular}.#{name}, label: '#{ name.to_s.humanize }') %>"
|
9
9
|
end
|
10
10
|
|
11
11
|
def line_field_output
|
@@ -30,5 +30,21 @@ class TimeField < Field
|
|
30
30
|
# "expect(page).to have_content(#{singular}#{1}.#{name})"
|
31
31
|
end
|
32
32
|
|
33
|
+
def search_field_output
|
34
|
+
" <div data-controller='time-range-picker' >"+
|
35
|
+
"\n <%= f.select 'q[0][#{name}_match]', options_for_select([['', ''], ['is at exactly', 'is_at_exactly']], @q[\'0\']['#{name}_match']), {} ," +
|
36
|
+
"\n { class: 'form-control match', 'data-action': 'change->time-range-picker#matchSelection' } %>"+
|
37
|
+
"\n <%= time_field_localized f, 'q[0][#{name}_search_start]', @q[\'0\'][:#{name}_search_start], autocomplete: 'off', size: 40, class: 'form-control', type: 'text', placeholder: 'start', 'data-time-range-picker-target': 'start' %>" +
|
38
|
+
"\n <%= time_field_localized f, 'q[0][#{name}_search_end]', @q[\'0\'][:#{name}_search_end], autocomplete: 'off', size: 40, class: 'form-control', type: 'text', placeholder: 'end' , 'data-time-range-picker-target': 'end' %>" +
|
39
|
+
"\n </div>"
|
40
|
+
end
|
41
|
+
|
33
42
|
|
43
|
+
def where_query_statement
|
44
|
+
".where(*#{name}_query)"
|
45
|
+
end
|
46
|
+
|
47
|
+
def load_all_query_statement
|
48
|
+
"#{name}_query = time_query_constructor(:#{name}, @q['0'][:#{name}_match], @q['0'][:#{name}_search_start], @q['0'][:#{name}_search_end])"
|
49
|
+
end
|
34
50
|
end
|
@@ -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
|
@@ -90,6 +89,28 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
90
89
|
class_option :display_as, default: {}
|
91
90
|
class_option :pundit, default: nil
|
92
91
|
class_option :related_sets, default: ''
|
92
|
+
class_option :code_before_create, default: nil
|
93
|
+
class_option :code_after_create, default: nil
|
94
|
+
class_option :code_before_update, default: nil
|
95
|
+
class_option :code_after_update, default: nil
|
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
|
+
|
93
114
|
|
94
115
|
def initialize(*meta_args)
|
95
116
|
super
|
@@ -291,6 +312,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
291
312
|
|
292
313
|
@no_edit = options['no_edit'] || false
|
293
314
|
@no_list = options['no_list'] || false
|
315
|
+
|
294
316
|
@no_controller = options['no_controller'] || false
|
295
317
|
@no_list = options['no_list'] || false
|
296
318
|
@no_list_label = options['no_list_label'] || false
|
@@ -426,6 +448,11 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
426
448
|
@no_field_form = true
|
427
449
|
end
|
428
450
|
|
451
|
+
@code_before_create = options['code_before_create']
|
452
|
+
@code_after_create = options['code_after_create']
|
453
|
+
@code_before_update = options['code_before_update']
|
454
|
+
@code_after_update = options['code_after_update']
|
455
|
+
|
429
456
|
buttons_width = ((!@no_edit && 1) || 0) + ((!@no_delete && 1) || 0) + @magic_buttons.count
|
430
457
|
|
431
458
|
|
@@ -462,6 +489,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
462
489
|
@columns_map[col] = this_column_object.field
|
463
490
|
end
|
464
491
|
|
492
|
+
|
465
493
|
@columns_map.each do |key, field|
|
466
494
|
if field.is_a?(AssociationField)
|
467
495
|
if @modify_as && @modify_as[key] && @modify_as[key][:typeahead]
|
@@ -481,11 +509,42 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
481
509
|
end
|
482
510
|
end
|
483
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
|
484
540
|
|
485
541
|
|
486
542
|
# create the template object
|
543
|
+
|
544
|
+
|
487
545
|
if @markup == "erb"
|
488
546
|
@template_builder = HotGlue::ErbTemplate.new(
|
547
|
+
layout_object: @layout_object,
|
489
548
|
layout_strategy: @layout_strategy,
|
490
549
|
magic_buttons: @magic_buttons,
|
491
550
|
small_buttons: @small_buttons,
|
@@ -501,7 +560,14 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
501
560
|
attachments: @attachments,
|
502
561
|
columns_map: @columns_map,
|
503
562
|
pundit: @pundit,
|
504
|
-
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
|
505
571
|
)
|
506
572
|
elsif @markup == "slim"
|
507
573
|
raise(HotGlue::Error, "SLIM IS NOT IMPLEMENTED")
|
@@ -509,10 +575,6 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
509
575
|
raise(HotGlue::Error, "HAML IS NOT IMPLEMENTED")
|
510
576
|
end
|
511
577
|
|
512
|
-
builder = HotGlue::Layout::Builder.new(generator: self,
|
513
|
-
include_setting: options['include'],
|
514
|
-
buttons_width: buttons_width)
|
515
|
-
@layout_object = builder.construct
|
516
578
|
|
517
579
|
@menu_file_exists = true if @nested_set.none? && File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
|
518
580
|
|
@@ -679,6 +741,9 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
679
741
|
@columns = @the_object.columns.map(&:name).map(&:to_sym).reject { |field| !@include_fields.include?(field) }
|
680
742
|
end
|
681
743
|
|
744
|
+
|
745
|
+
@columns = @columns -@nested_set.collect { |set| (set[:singular] + "_id").to_sym }
|
746
|
+
|
682
747
|
if @attachments.any?
|
683
748
|
puts "Adding attachments-as-columns: #{@attachments}"
|
684
749
|
@attachments.keys.each do |attachment|
|
@@ -724,8 +789,17 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
724
789
|
if @factory_creation == ''
|
725
790
|
"@#{singular } = #{ class_name }.new(modified_params)"
|
726
791
|
else
|
727
|
-
|
728
|
-
|
792
|
+
res = +"begin
|
793
|
+
#{@factory_creation}
|
794
|
+
"
|
795
|
+
res << "\n" + "@#{singular} = factory.#{singular}" unless res.include?("@#{singular} = factory.#{singular}")
|
796
|
+
res << "flash[:notice] = \"Successfully created \#{@#{singular}.name}\" unless @#{singular}.new_record?
|
797
|
+
rescue ActiveRecord::RecordInvalid
|
798
|
+
@#{singular} = factory.#{singular}
|
799
|
+
flash[:alert] = \"Oops, your #{singular} could not be created. #{@hawk_alarm}\"
|
800
|
+
@action = 'new'
|
801
|
+
end"
|
802
|
+
res
|
729
803
|
end
|
730
804
|
end
|
731
805
|
|
@@ -743,6 +817,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
743
817
|
|
744
818
|
def copy_controller_and_spec_files
|
745
819
|
@default_colspan = @columns.size
|
820
|
+
|
746
821
|
unless @specs_only || @no_controller
|
747
822
|
template "controller.rb.erb", File.join("#{filepath_prefix}app/controllers#{namespace_with_dash}", "#{@controller_build_folder}_controller.rb")
|
748
823
|
if @namespace
|
@@ -807,7 +882,6 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
807
882
|
|
808
883
|
def list_column_headings
|
809
884
|
@template_builder.list_column_headings(
|
810
|
-
layout_object: @layout_object,
|
811
885
|
col_identifier: @layout_strategy.column_classes_for_column_headings,
|
812
886
|
column_width: @layout_strategy.column_width,
|
813
887
|
singular: @singular
|
@@ -1086,6 +1160,10 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1086
1160
|
|
1087
1161
|
def copy_view_files
|
1088
1162
|
return if @specs_only
|
1163
|
+
@edit_within_form_partial = File.exist?("#{filepath_prefix}app/views#{namespace_with_dash}/#{@controller_build_folder}/_edit_within_form.html.#{@markup}")
|
1164
|
+
@edit_after_form_partial = File.exist?("#{filepath_prefix}app/views#{namespace_with_dash}/#{@controller_build_folder}/_edit_within_form.html.#{@markup}")
|
1165
|
+
@new_within_form_partial = File.exist?("#{filepath_prefix}app/views#{namespace_with_dash}/#{@controller_build_folder}/_new_within_form.html.#{@markup}")
|
1166
|
+
@new_after_form_partial = File.exist?("#{filepath_prefix}app/views#{namespace_with_dash}/#{@controller_build_folder}/_new_within_form.html.#{@markup}")
|
1089
1167
|
|
1090
1168
|
if @no_controller
|
1091
1169
|
File.write("#{Rails.root}/app/views/#{namespace_with_trailing_dash}/#{plural}/REGENERATE.md", regenerate_me_code)
|
@@ -1229,8 +1307,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1229
1307
|
end
|
1230
1308
|
|
1231
1309
|
def form_fields_html
|
1232
|
-
@template_builder.all_form_fields(layout_strategy: @layout_strategy
|
1233
|
-
layout_object: @layout_object)
|
1310
|
+
@template_builder.all_form_fields(layout_strategy: @layout_strategy)
|
1234
1311
|
end
|
1235
1312
|
|
1236
1313
|
def list_label
|
@@ -1245,8 +1322,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1245
1322
|
@template_builder.all_line_fields(
|
1246
1323
|
col_identifier: @layout_strategy.column_classes_for_line_fields,
|
1247
1324
|
perc_width: @layout_strategy.each_col, # undefined method `each_col'
|
1248
|
-
layout_strategy: @layout_strategy
|
1249
|
-
layout_object: @layout_object
|
1325
|
+
layout_strategy: @layout_strategy
|
1250
1326
|
)
|
1251
1327
|
end
|
1252
1328
|
|
@@ -1364,8 +1440,55 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1364
1440
|
end
|
1365
1441
|
end
|
1366
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
|
+
|
1367
1485
|
private # thor does something fancy like sending the class all of its own methods during some strange run sequence
|
1368
1486
|
# does not like public methods
|
1487
|
+
|
1488
|
+
def spaces(num)
|
1489
|
+
" " * num
|
1490
|
+
end
|
1491
|
+
|
1369
1492
|
def cc_filename_with_extensions(name, file_format = format)
|
1370
1493
|
[name, file_format].compact.join(".")
|
1371
1494
|
end
|
@@ -1396,8 +1519,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1396
1519
|
|
1397
1520
|
def turbo_parental_updates
|
1398
1521
|
@nested_set.collect { |data|
|
1399
|
-
"<%= turbo_stream.replace \"#{@namespace
|
1400
|
-
<%= 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} %>
|
1401
1524
|
<% end %>"
|
1402
1525
|
}.join("\n")
|
1403
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
|
+
|