b4um_generators 0.1.0

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.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +28 -0
  4. data/CHANGELOG.md +5 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.de.md +821 -0
  7. data/README.md +815 -0
  8. data/Rakefile +12 -0
  9. data/b4um_generators.gemspec +30 -0
  10. data/bin/console +11 -0
  11. data/bin/setup +8 -0
  12. data/lib/b4um_generators/version.rb +5 -0
  13. data/lib/b4um_generators.rb +8 -0
  14. data/lib/generators/b4um/bento/bento_generator.rb +81 -0
  15. data/lib/generators/b4um/bento/templates/_alternating.html.erb.tt +15 -0
  16. data/lib/generators/b4um/bento/templates/_bento.html.erb.tt +26 -0
  17. data/lib/generators/b4um/bento/templates/_grid.html.erb.tt +13 -0
  18. data/lib/generators/b4um/bento/templates/_list.html.erb.tt +15 -0
  19. data/lib/generators/b4um/comments/comments_generator.rb +259 -0
  20. data/lib/generators/b4um/comments/templates/_comments.html.erb.tt +63 -0
  21. data/lib/generators/b4um/comments/templates/comment.rb.tt +5 -0
  22. data/lib/generators/b4um/comments/templates/comments_controller.rb.tt +45 -0
  23. data/lib/generators/b4um/comments/templates/create_comments.rb.tt +14 -0
  24. data/lib/generators/b4um/controller/controller_generator.rb +397 -0
  25. data/lib/generators/b4um/help/help_generator.rb +755 -0
  26. data/lib/generators/b4um/infinite_scroll/infinite_scroll_generator.rb +199 -0
  27. data/lib/generators/b4um/infinite_scroll/templates/infinite_scroll_controller.js +61 -0
  28. data/lib/generators/b4um/install/install_generator.rb +492 -0
  29. data/lib/generators/b4um/install/templates/_cookie_consent.html.erb +27 -0
  30. data/lib/generators/b4um/install/templates/_footer.html.erb +17 -0
  31. data/lib/generators/b4um/install/templates/_hero.html.erb +33 -0
  32. data/lib/generators/b4um/install/templates/_navigation.html.erb +31 -0
  33. data/lib/generators/b4um/install/templates/_sitemap.html.erb +48 -0
  34. data/lib/generators/b4um/install/templates/_theme_switcher.html.erb +57 -0
  35. data/lib/generators/b4um/install/templates/b4um/badges.css +43 -0
  36. data/lib/generators/b4um/install/templates/b4um/base.css +42 -0
  37. data/lib/generators/b4um/install/templates/b4um/callouts.css +58 -0
  38. data/lib/generators/b4um/install/templates/b4um/cards.css +401 -0
  39. data/lib/generators/b4um/install/templates/b4um/comments.css +52 -0
  40. data/lib/generators/b4um/install/templates/b4um/cookie-consent.css +83 -0
  41. data/lib/generators/b4um/install/templates/b4um/empty-state.css +26 -0
  42. data/lib/generators/b4um/install/templates/b4um/flash.css +86 -0
  43. data/lib/generators/b4um/install/templates/b4um/footer.css +338 -0
  44. data/lib/generators/b4um/install/templates/b4um/forms.css +924 -0
  45. data/lib/generators/b4um/install/templates/b4um/hero.css +149 -0
  46. data/lib/generators/b4um/install/templates/b4um/layout.css +166 -0
  47. data/lib/generators/b4um/install/templates/b4um/lightbox.css +268 -0
  48. data/lib/generators/b4um/install/templates/b4um/navigation.css +257 -0
  49. data/lib/generators/b4um/install/templates/b4um/pagination.css +85 -0
  50. data/lib/generators/b4um/install/templates/b4um/resources.css +121 -0
  51. data/lib/generators/b4um/install/templates/b4um/search.css +41 -0
  52. data/lib/generators/b4um/install/templates/b4um/tables.css +67 -0
  53. data/lib/generators/b4um/install/templates/b4um/theme-switcher.css +178 -0
  54. data/lib/generators/b4um/install/templates/b4um/theme.css +132 -0
  55. data/lib/generators/b4um/install/templates/b4um.css +20 -0
  56. data/lib/generators/b4um/install/templates/b4um.yml +12 -0
  57. data/lib/generators/b4um/install/templates/b4um_helper.rb +27 -0
  58. data/lib/generators/b4um/install/templates/cookie_consent_controller.js +76 -0
  59. data/lib/generators/b4um/install/templates/dismissible_controller.js +7 -0
  60. data/lib/generators/b4um/install/templates/image_lightbox_controller.js +414 -0
  61. data/lib/generators/b4um/install/templates/image_preview_controller.js +85 -0
  62. data/lib/generators/b4um/install/templates/navigation_controller.js +25 -0
  63. data/lib/generators/b4um/install/templates/navigation_helper.rb +26 -0
  64. data/lib/generators/b4um/install/templates/sitemap_controller.js +35 -0
  65. data/lib/generators/b4um/install/templates/theme_controller.js +122 -0
  66. data/lib/generators/b4um/pagination/pagination_generator.rb +179 -0
  67. data/lib/generators/b4um/pagination/templates/_pagination.html.erb.tt +48 -0
  68. data/lib/generators/b4um/pagination/templates/pagination.rb +36 -0
  69. data/lib/generators/b4um/scaffold/scaffold_generator.rb +333 -0
  70. data/lib/generators/b4um/scaffold/templates/_bento.html.erb.tt +26 -0
  71. data/lib/generators/b4um/scaffold/templates/_form.html.erb.tt +218 -0
  72. data/lib/generators/b4um/scaffold/templates/_resource.html.erb.tt +144 -0
  73. data/lib/generators/b4um/scaffold/templates/_table.html.erb.tt +40 -0
  74. data/lib/generators/b4um/scaffold/templates/edit.html.erb.tt +21 -0
  75. data/lib/generators/b4um/scaffold/templates/index.html.erb.tt +24 -0
  76. data/lib/generators/b4um/scaffold/templates/new.html.erb.tt +17 -0
  77. data/lib/generators/b4um/scaffold/templates/show.html.erb.tt +31 -0
  78. data/lib/generators/b4um/search/search_generator.rb +165 -0
  79. data/lib/generators/b4um/search/templates/search.rb +34 -0
  80. data/lib/generators/b4um/search/templates/search_form.html.erb.tt +15 -0
  81. data/lib/generators/b4um/table/table_generator.rb +63 -0
  82. data/lib/generators/b4um/table/templates/_table.html.erb.tt +40 -0
  83. data/lib/generators/b4um/trix/templates/b4um_rich_text_helper.rb +58 -0
  84. data/lib/generators/b4um/trix/templates/b4um_trix.js +551 -0
  85. data/lib/generators/b4um/trix/trix_generator.rb +383 -0
  86. data/sig/b4um_generators.rbs +4 -0
  87. metadata +148 -0
@@ -0,0 +1,218 @@
1
+ <%%= form_with(model: <%= singular_table_name %>, class: "form") do |form| %>
2
+ <%% if <%= singular_table_name %>.errors.any? %>
3
+ <div class="error-messages">
4
+ <h2>
5
+ <%%= pluralize(<%= singular_table_name %>.errors.count, "error") %>
6
+ prohibited this <%= singular_table_name %> from being saved:
7
+ </h2>
8
+
9
+ <ul>
10
+ <%% <%= singular_table_name %>.errors.each do |error| %>
11
+ <li><%%= error.full_message %></li>
12
+ <%% end %>
13
+ </ul>
14
+ </div>
15
+ <%% end %>
16
+
17
+ <% attributes.each do |attribute| -%>
18
+ <% if attribute.name == "password_digest" -%>
19
+ <div class="form-field">
20
+ <%%= form.password_field :password,
21
+ class: "form-input",
22
+ placeholder: " " %>
23
+ <%%= form.label :password, class: "form-label" %>
24
+ </div>
25
+
26
+ <div class="form-field">
27
+ <%%= form.password_field :password_confirmation,
28
+ class: "form-input",
29
+ placeholder: " " %>
30
+ <%%= form.label :password_confirmation, class: "form-label" %>
31
+ </div>
32
+
33
+ <% elsif attribute.name.match?(/(?:^|_)email(?:_|$)/) -%>
34
+ <div class="form-field">
35
+ <%%= form.email_field :<%= attribute.name %>,
36
+ class: "form-input",
37
+ placeholder: " " %>
38
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
39
+ </div>
40
+
41
+ <% elsif attribute.name.match?(/(?:^|_)(?:password|password_confirmation)(?:_|$)/) -%>
42
+ <div class="form-field">
43
+ <%%= form.password_field :<%= attribute.name %>,
44
+ class: "form-input",
45
+ placeholder: " " %>
46
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
47
+ </div>
48
+
49
+ <% elsif attribute.name.match?(/(?:^|_)(?:phone|telephone|mobile)(?:_|$)/) -%>
50
+ <div class="form-field">
51
+ <%%= form.telephone_field :<%= attribute.name %>,
52
+ class: "form-input",
53
+ placeholder: " " %>
54
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
55
+ </div>
56
+
57
+ <% elsif attribute.name.match?(/(?:^|_)(?:url|website|homepage)(?:_|$)/) -%>
58
+ <div class="form-field">
59
+ <%%= form.url_field :<%= attribute.name %>,
60
+ class: "form-input",
61
+ placeholder: " " %>
62
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
63
+ </div>
64
+
65
+ <% elsif attribute.type == :boolean -%>
66
+ <div class="form-field form-field--checkbox">
67
+ <%%= form.check_box :<%= attribute.name %>, class: "form-checkbox" %>
68
+ <%%= form.label :<%= attribute.name %>, class: "form-label form-label--checkbox" %>
69
+ </div>
70
+
71
+ <% elsif attribute.type == :text -%>
72
+ <div class="form-field form-field--textarea">
73
+ <%%= form.text_area :<%= attribute.name %>,
74
+ class: "form-textarea",
75
+ placeholder: " " %>
76
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
77
+ </div>
78
+
79
+ <% elsif [:integer, :float, :decimal].include?(attribute.type) -%>
80
+ <div class="form-field">
81
+ <%%= form.number_field :<%= attribute.name %>,
82
+ class: "form-input",
83
+ placeholder: " " %>
84
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
85
+ </div>
86
+
87
+ <% elsif attribute.type == :date -%>
88
+ <div class="form-field">
89
+ <%%= form.date_field :<%= attribute.name %>,
90
+ class: "form-input",
91
+ placeholder: " " %>
92
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
93
+ </div>
94
+
95
+ <% elsif [:datetime, :timestamp].include?(attribute.type) -%>
96
+ <div class="form-field">
97
+ <%%= form.datetime_local_field :<%= attribute.name %>,
98
+ class: "form-input",
99
+ placeholder: " " %>
100
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
101
+ </div>
102
+
103
+ <% elsif attribute.type == :time -%>
104
+ <div class="form-field">
105
+ <%%= form.time_field :<%= attribute.name %>,
106
+ class: "form-input",
107
+ placeholder: " " %>
108
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
109
+ </div>
110
+
111
+ <% elsif attribute.type == :attachment -%>
112
+ <div class="form-field form-field--file"
113
+ data-controller="image-preview">
114
+
115
+ <div class="form-file-control">
116
+ <%%= form.label :<%= attribute.name %>,
117
+ class: "form-file-label" %>
118
+
119
+ <%%= form.file_field :<%= attribute.name %>,
120
+ class: "form-file-input",
121
+ accept: "image/*",
122
+ data: {
123
+ image_preview_target: "input",
124
+ action: "change->image-preview#preview"
125
+ } %>
126
+ </div>
127
+
128
+ <div class="form-image-preview"
129
+ data-image-preview-target="container"
130
+ <%%= "hidden" unless <%= singular_table_name %>.<%= attribute.name %>.attached? %>>
131
+
132
+ <%% if <%= singular_table_name %>.<%= attribute.name %>.attached? %>
133
+ <%%= image_tag <%= singular_table_name %>.<%= attribute.name %>,
134
+ class: "form-image-preview__image",
135
+ alt: <%= singular_table_name %>.<%= attribute.name %>.filename.to_s,
136
+ data: {
137
+ image_preview_target: "image"
138
+ } %>
139
+ <%% else %>
140
+ <img class="form-image-preview__image"
141
+ data-image-preview-target="image"
142
+ alt="Image preview">
143
+ <%% end %>
144
+ </div>
145
+ </div>
146
+
147
+ <% elsif attribute.type == :attachments -%>
148
+ <div class="form-field form-field--file"
149
+ data-controller="image-preview">
150
+
151
+ <div class="form-file-control">
152
+ <%%= form.label :<%= attribute.name %>,
153
+ class: "form-file-label" %>
154
+
155
+ <%% <%= singular_table_name %>.<%= attribute.name %>.each do |image| %>
156
+ <%%= form.hidden_field :<%= attribute.name %>,
157
+ multiple: true,
158
+ value: image.signed_id %>
159
+ <%% end %>
160
+
161
+ <%%= form.file_field :<%= attribute.name %>,
162
+ class: "form-file-input",
163
+ accept: "image/*",
164
+ multiple: true,
165
+ data: {
166
+ image_preview_target: "input",
167
+ action: "change->image-preview#previewMultiple"
168
+ } %>
169
+ </div>
170
+
171
+ <div class="form-image-preview form-image-preview--multiple"
172
+ data-image-preview-target="container"
173
+ <%%= "hidden" unless <%= singular_table_name %>.<%= attribute.name %>.attached? %>>
174
+
175
+ <%% <%= singular_table_name %>.<%= attribute.name %>.each do |image| %>
176
+ <div class="form-image-preview__item"
177
+ role="button"
178
+ tabindex="0"
179
+ aria-pressed="false"
180
+ data-image-preview-target="existingItem"
181
+ data-action="click->image-preview#toggleRemoval keydown->image-preview#toggleRemovalWithKeyboard">
182
+
183
+ <%%= image_tag image,
184
+ class: "form-image-preview__image",
185
+ alt: image.filename.to_s %>
186
+
187
+ <%%= check_box_tag(
188
+ "<%= singular_table_name %>[remove_<%= attribute.name %>_ids][]",
189
+ image.id,
190
+ false,
191
+ class: "form-image-preview__remove-checkbox",
192
+ data: {
193
+ image_preview_target: "removeCheckbox"
194
+ }
195
+ ) %>
196
+
197
+ <div class="form-image-preview__remove-status">
198
+ Will be removed
199
+ </div>
200
+ </div>
201
+ <%% end %>
202
+ </div>
203
+ </div>
204
+
205
+ <% else -%>
206
+ <div class="form-field">
207
+ <%%= form.<%= attribute.field_type %> :<%= attribute.name %>,
208
+ class: "form-input",
209
+ placeholder: " " %>
210
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
211
+ </div>
212
+ <% end -%>
213
+ <% end -%>
214
+
215
+ <div class="form-actions">
216
+ <%%= form.submit class: "form-submit" %>
217
+ </div>
218
+ <%% end %>
@@ -0,0 +1,144 @@
1
+ <div id="<%%= dom_id <%= singular_table_name %> %>" class="resource">
2
+ <% attributes.reject { |attribute| attribute.name == "password_digest" }.each do |attribute| -%>
3
+ <div class="resource-field">
4
+ <strong class="resource-label"><%= attribute.human_name %>:</strong>
5
+ <% if attribute.type == :boolean -%>
6
+ <span class="resource-value"><%%= <%= singular_table_name %>.<%= attribute.name %> ? "Yes" : "No" %></span>
7
+ <% elsif attribute.type == :attachment -%>
8
+ <div class="resource-image"
9
+ data-controller="image-lightbox"
10
+ data-action="keydown->image-lightbox#keydown">
11
+
12
+ <%% if <%= singular_table_name %>.<%= attribute.name %>.attached? %>
13
+ <button type="button"
14
+ class="resource-image__button"
15
+ data-image-lightbox-target="item"
16
+ data-image-lightbox-url="<%%= url_for(<%= singular_table_name %>.<%= attribute.name %>) %>"
17
+ data-image-lightbox-alt="<%%= <%= singular_table_name %>.<%= attribute.name %>.filename.to_s %>"
18
+ data-action="click->image-lightbox#open">
19
+
20
+ <%%= image_tag <%= singular_table_name %>.<%= attribute.name %>,
21
+ class: "resource-image__image",
22
+ alt: <%= singular_table_name %>.<%= attribute.name %>.filename.to_s %>
23
+ </button>
24
+
25
+ <div class="image-lightbox"
26
+ data-image-lightbox-target="overlay"
27
+ data-action="click->image-lightbox#closeOnBackground"
28
+ tabindex="-1"
29
+ role="dialog"
30
+ aria-modal="true"
31
+ aria-label="Image preview"
32
+ hidden>
33
+
34
+ <div class="image-lightbox__counter"
35
+ data-image-lightbox-target="counter"></div>
36
+
37
+ <button type="button"
38
+ class="image-lightbox__close"
39
+ aria-label="Close image"
40
+ data-action="click->image-lightbox#close">
41
+ &times;
42
+ </button>
43
+
44
+ <div class="image-lightbox__stage"
45
+ data-image-lightbox-target="stage"
46
+ data-action="pointerdown->image-lightbox#pointerDown pointermove->image-lightbox#pointerMove pointerup->image-lightbox#pointerUp pointercancel->image-lightbox#pointerCancel">
47
+ <img class="image-lightbox__image"
48
+ data-image-lightbox-target="image"
49
+ alt="">
50
+ </div>
51
+
52
+ <div class="image-lightbox__caption"
53
+ data-image-lightbox-target="caption"></div>
54
+ </div>
55
+ <%% else %>
56
+ <span class="resource-value resource-value--empty">No image</span>
57
+ <%% end %>
58
+ </div>
59
+ <% elsif attribute.type == :attachments -%>
60
+ <div class="resource-images"
61
+ data-controller="image-lightbox"
62
+ data-action="keydown->image-lightbox#keydown">
63
+
64
+ <%% if <%= singular_table_name %>.<%= attribute.name %>.attached? %>
65
+ <%% <%= singular_table_name %>.<%= attribute.name %>.each do |image| %>
66
+ <button type="button"
67
+ class="resource-images__button"
68
+ data-image-lightbox-target="item"
69
+ data-image-lightbox-url="<%%= url_for(image) %>"
70
+ data-image-lightbox-alt="<%%= image.filename.to_s %>"
71
+ data-action="click->image-lightbox#open">
72
+
73
+ <%%= image_tag image,
74
+ class: "resource-images__image",
75
+ alt: image.filename.to_s %>
76
+ </button>
77
+ <%% end %>
78
+
79
+ <div class="image-lightbox"
80
+ data-image-lightbox-target="overlay"
81
+ data-action="click->image-lightbox#closeOnBackground"
82
+ tabindex="-1"
83
+ role="dialog"
84
+ aria-modal="true"
85
+ aria-label="Image gallery"
86
+ hidden>
87
+
88
+ <div class="image-lightbox__counter"
89
+ data-image-lightbox-target="counter"></div>
90
+
91
+ <button type="button"
92
+ class="image-lightbox__close"
93
+ aria-label="Close gallery"
94
+ data-action="click->image-lightbox#close">
95
+ &times;
96
+ </button>
97
+
98
+ <button type="button"
99
+ class="image-lightbox__navigation image-lightbox__navigation--previous"
100
+ aria-label="Previous image"
101
+ data-image-lightbox-target="previousButton"
102
+ data-action="click->image-lightbox#previous">
103
+ &#8249;
104
+ </button>
105
+
106
+ <div class="image-lightbox__stage"
107
+ data-image-lightbox-target="stage"
108
+ data-action="pointerdown->image-lightbox#pointerDown pointermove->image-lightbox#pointerMove pointerup->image-lightbox#pointerUp pointercancel->image-lightbox#pointerCancel">
109
+ <img class="image-lightbox__image"
110
+ data-image-lightbox-target="image"
111
+ alt="">
112
+ </div>
113
+
114
+ <button type="button"
115
+ class="image-lightbox__navigation image-lightbox__navigation--next"
116
+ aria-label="Next image"
117
+ data-image-lightbox-target="nextButton"
118
+ data-action="click->image-lightbox#next">
119
+ &#8250;
120
+ </button>
121
+
122
+ <div class="image-lightbox__caption"
123
+ data-image-lightbox-target="caption"></div>
124
+ </div>
125
+ <%% else %>
126
+ <span class="resource-value resource-value--empty">No images</span>
127
+ <%% end %>
128
+ </div>
129
+ <% elsif attribute.name == "status" -%>
130
+ <span class="b4um-badge"><%%= <%= singular_table_name %>.<%= attribute.name %> %></span>
131
+ <% elsif attribute.type == :text -%>
132
+ <span class="resource-value">
133
+ <%% if local_assigns[:compact] %>
134
+ <%%= truncate(<%= singular_table_name %>.<%= attribute.name %>, length: 160) %>
135
+ <%% else %>
136
+ <%%= <%= singular_table_name %>.<%= attribute.name %> %>
137
+ <%% end %>
138
+ </span>
139
+ <% else -%>
140
+ <span class="resource-value"><%%= <%= singular_table_name %>.<%= attribute.name %> %></span>
141
+ <% end -%>
142
+ </div>
143
+ <% end -%>
144
+ </div>
@@ -0,0 +1,40 @@
1
+ <div class="b4um-table-wrapper">
2
+ <table class="b4um-table">
3
+ <thead>
4
+ <tr>
5
+ <% attributes.each do |attribute| -%>
6
+ <th><%= attribute.name.humanize %></th>
7
+ <% end -%>
8
+ <th>Actions</th>
9
+ </tr>
10
+ </thead>
11
+
12
+ <tbody>
13
+ <%% <%= plural_table_name %>.each do |<%= singular_table_name %>| %>
14
+ <tr>
15
+ <% attributes.each do |attribute| -%>
16
+ <td>
17
+ <% if attribute.name == "status" -%>
18
+ <span class="b4um-badge">
19
+ <%%= <%= singular_table_name %>.<%= attribute.name %> %>
20
+ </span>
21
+ <% elsif attribute.type == :text -%>
22
+ <%%= truncate(<%= singular_table_name %>.<%= attribute.name %>, length: 100) %>
23
+ <% else -%>
24
+ <%%= <%= singular_table_name %>.<%= attribute.name %> %>
25
+ <% end -%>
26
+ </td>
27
+ <% end -%>
28
+
29
+ <td>
30
+ <div class="b4um-table__actions">
31
+ <%%= link_to "Show",
32
+ <%= singular_table_name %>,
33
+ class: "button button--secondary" %>
34
+ </div>
35
+ </td>
36
+ </tr>
37
+ <%% end %>
38
+ </tbody>
39
+ </table>
40
+ </div>
@@ -0,0 +1,21 @@
1
+ <%% content_for :title, "Editing <%= singular_table_name.humanize.downcase %>" %>
2
+
3
+ <div class="page-header">
4
+ <h1>Editing <%= singular_table_name.humanize.downcase %></h1>
5
+ </div>
6
+
7
+ <div class="b4um-grid">
8
+ <section class="b4um-card b4um-card--full">
9
+ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
10
+
11
+ <div class="b4um-card__actions">
12
+ <%%= link_to "Show",
13
+ @<%= singular_table_name %>,
14
+ class: "button button--secondary" %>
15
+
16
+ <%%= link_to "Back",
17
+ <%= plural_route_name %>_path,
18
+ class: "button button--secondary" %>
19
+ </div>
20
+ </section>
21
+ </div>
@@ -0,0 +1,24 @@
1
+ <%% content_for :title, "<%= plural_table_name.humanize %>" %>
2
+
3
+ <div class="page-header">
4
+ <h1><%= plural_table_name.humanize %></h1>
5
+
6
+ <%%= link_to "New <%= singular_table_name.humanize.downcase %>",
7
+ new_<%= singular_route_name %>_path,
8
+ class: "button button--primary" %>
9
+ </div>
10
+
11
+ <%% if @<%= plural_table_name %>.any? %>
12
+ <%%= render "<%= options[:layout] %>",
13
+ <%= plural_table_name %>: @<%= plural_table_name %> %>
14
+ <%% else %>
15
+ <section class="b4um-empty-state">
16
+ <h2 class="b4um-empty-state__title">
17
+ No <%= plural_table_name.humanize.downcase %> yet.
18
+ </h2>
19
+
20
+ <p class="b4um-empty-state__text">
21
+ Create your first <%= singular_table_name.humanize.downcase %> to get started.
22
+ </p>
23
+ </section>
24
+ <%% end %>
@@ -0,0 +1,17 @@
1
+ <%% content_for :title, "New <%= singular_table_name.humanize.downcase %>" %>
2
+
3
+ <div class="page-header">
4
+ <h1>New <%= singular_table_name.humanize.downcase %></h1>
5
+ </div>
6
+
7
+ <div class="b4um-grid">
8
+ <section class="b4um-card b4um-card--full">
9
+ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
10
+
11
+ <div class="b4um-card__actions">
12
+ <%%= link_to "Back",
13
+ <%= plural_route_name %>_path,
14
+ class: "button button--secondary" %>
15
+ </div>
16
+ </section>
17
+ </div>
@@ -0,0 +1,31 @@
1
+ <%% content_for :title, "<%= singular_table_name.humanize %>" %>
2
+
3
+ <div class="page-header">
4
+ <h1><%= singular_table_name.humanize %></h1>
5
+ </div>
6
+
7
+ <div class="b4um-grid">
8
+ <article class="b4um-card b4um-card--full">
9
+ <%%= render @<%= singular_table_name %> %>
10
+
11
+ <div class="b4um-card__actions">
12
+ <%%= link_to "Edit",
13
+ edit_<%= singular_route_name %>_path(@<%= singular_table_name %>),
14
+ class: "button button--secondary" %>
15
+
16
+ <%%= link_to "Back",
17
+ <%= plural_route_name %>_path,
18
+ class: "button button--secondary" %>
19
+
20
+ <%%= button_to "Destroy",
21
+ @<%= singular_table_name %>,
22
+ method: :delete,
23
+ class: "button button--danger",
24
+ form: {
25
+ data: {
26
+ turbo_confirm: "Are you sure?"
27
+ }
28
+ } %>
29
+ </div>
30
+ </article>
31
+ </div>
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "erb"
5
+
6
+ module B4um
7
+ module Generators
8
+ class SearchGenerator < Rails::Generators::NamedBase
9
+ source_root File.expand_path("templates", __dir__)
10
+
11
+ class << self
12
+ def desc(_description = nil)
13
+ "Adds B4UM search to an existing resource."
14
+ end
15
+ end
16
+
17
+ def validate_model
18
+ return if File.exist?(
19
+ File.join(destination_root, model_path)
20
+ )
21
+
22
+ raise Thor::Error, "Model not found: #{model_path}"
23
+ end
24
+
25
+ def validate_controller
26
+ return if File.exist?(
27
+ File.join(destination_root, controller_path)
28
+ )
29
+
30
+ raise Thor::Error, "Controller not found: #{controller_path}"
31
+ end
32
+
33
+ def validate_index_view
34
+ return if File.exist?(
35
+ File.join(destination_root, index_view_path)
36
+ )
37
+
38
+ raise Thor::Error, "Index view not found: #{index_view_path}"
39
+ end
40
+
41
+ def create_search_concern
42
+ template(
43
+ "search.rb",
44
+ "app/controllers/concerns/b4um_search.rb"
45
+ )
46
+ end
47
+
48
+ def update_controller
49
+ controller_content = File.read(
50
+ File.join(destination_root, controller_path)
51
+ )
52
+
53
+ return if controller_content.include?("include B4umSearch")
54
+
55
+ inject_into_class(
56
+ controller_path,
57
+ "#{class_name.pluralize}Controller",
58
+ " include B4umSearch\n\n"
59
+ )
60
+ end
61
+
62
+ def update_index_action
63
+ controller_file = File.join(
64
+ destination_root,
65
+ controller_path
66
+ )
67
+
68
+ controller_content = File.read(controller_file)
69
+
70
+ search_pattern = /
71
+ b4um_search\(\s*
72
+ #{Regexp.escape(class_name)}\.all,\s*
73
+ params\[:q\]\s*
74
+ \)
75
+ /x
76
+
77
+ return if controller_content.match?(search_pattern)
78
+
79
+ pagination_pattern = /
80
+ (@#{file_name.pluralize},\s*@pagination\s*=\s*b4um_paginate\(\s*)
81
+ #{Regexp.escape(class_name)}\.all
82
+ (\s*,)
83
+ /x
84
+
85
+ if controller_content.match?(pagination_pattern)
86
+ gsub_file(
87
+ controller_path,
88
+ pagination_pattern,
89
+ "\\1b4um_search(#{class_name}.all, params[:q])\\2"
90
+ )
91
+
92
+ return
93
+ end
94
+
95
+ old_index = "@#{file_name.pluralize} = #{class_name}.all"
96
+
97
+ unless controller_content.include?(old_index)
98
+ raise Thor::Error,
99
+ "Could not find the index collection in #{controller_path}"
100
+ end
101
+
102
+ search_code = <<~RUBY.chomp
103
+ @#{file_name.pluralize} = b4um_search(
104
+ #{class_name}.all,
105
+ params[:q]
106
+ )
107
+ RUBY
108
+
109
+ gsub_file(
110
+ controller_path,
111
+ old_index,
112
+ search_code
113
+ )
114
+ end
115
+
116
+ def update_index_view
117
+ view_content = File.read(
118
+ File.join(destination_root, index_view_path)
119
+ )
120
+
121
+ return if view_content.include?(
122
+ 'class="b4um-search"'
123
+ )
124
+
125
+ template_content = ERB.new(
126
+ File.read(
127
+ File.join(
128
+ self.class.source_root,
129
+ "search_form.html.erb.tt"
130
+ )
131
+ )
132
+ ).result(binding)
133
+
134
+ prepend_to_file(
135
+ index_view_path,
136
+ "#{template_content}\n"
137
+ )
138
+ end
139
+
140
+ private
141
+
142
+ def model_path
143
+ File.join(
144
+ "app/models",
145
+ "#{file_name}.rb"
146
+ )
147
+ end
148
+
149
+ def controller_path
150
+ File.join(
151
+ "app/controllers",
152
+ "#{file_name.pluralize}_controller.rb"
153
+ )
154
+ end
155
+
156
+ def index_view_path
157
+ File.join(
158
+ "app/views",
159
+ file_name.pluralize,
160
+ "index.html.erb"
161
+ )
162
+ end
163
+ end
164
+ end
165
+ end