b4um_generators 0.1.1 → 0.2.8
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/.rubocop.yml +2 -2
- data/README.de.md +177 -5
- data/README.md +175 -5
- data/lib/b4um_generators/version.rb +1 -1
- data/lib/generators/b4um/attachment/attachment_generator.rb +514 -0
- data/lib/generators/b4um/authentication/authentication_generator.rb +769 -0
- data/lib/generators/b4um/authentication/templates/new.html.erb.tt +35 -0
- data/lib/generators/b4um/authentication/templates/sessions_controller.rb.tt +25 -0
- data/lib/generators/b4um/help/help_generator.rb +210 -5
- data/lib/generators/b4um/infinite_scroll/infinite_scroll_generator.rb +31 -0
- data/lib/generators/b4um/infinite_scroll/templates/infinite_scroll_controller.js +2 -2
- data/lib/generators/b4um/install/install_generator.rb +141 -2
- data/lib/generators/b4um/install/templates/b4um/forms.css +161 -1
- data/lib/generators/b4um/install/templates/b4um/navigation.css +13 -0
- data/lib/generators/b4um/install/templates/b4um/resources.css +18 -0
- data/lib/generators/b4um/install/templates/b4um.css +14 -0
- data/lib/generators/b4um/install/templates/navigation_helper.rb +13 -0
- data/lib/generators/b4um/readable/readable_generator.rb +77 -0
- data/lib/generators/b4um/search/search_generator.rb +58 -0
- metadata +7 -2
|
@@ -417,12 +417,20 @@
|
|
|
417
417
|
|
|
418
418
|
.form-field--rich-text {
|
|
419
419
|
display: grid;
|
|
420
|
-
grid-template-columns: 1fr;
|
|
420
|
+
grid-template-columns: minmax(0, 1fr);
|
|
421
|
+
|
|
422
|
+
width: 100%;
|
|
423
|
+
min-width: 0;
|
|
424
|
+
max-width: 100%;
|
|
421
425
|
}
|
|
422
426
|
|
|
423
427
|
.form-field--rich-text trix-toolbar {
|
|
424
428
|
grid-row: 1;
|
|
425
429
|
|
|
430
|
+
width: 100%;
|
|
431
|
+
min-width: 0;
|
|
432
|
+
max-width: 100%;
|
|
433
|
+
|
|
426
434
|
position: sticky;
|
|
427
435
|
top: 61px;
|
|
428
436
|
z-index: 10;
|
|
@@ -496,6 +504,15 @@
|
|
|
496
504
|
color: var(--b4um-text);
|
|
497
505
|
}
|
|
498
506
|
|
|
507
|
+
.form-field--rich-text .form-textarea,
|
|
508
|
+
.form-field--rich-text trix-editor {
|
|
509
|
+
width: 100%;
|
|
510
|
+
min-width: 0;
|
|
511
|
+
max-width: 100%;
|
|
512
|
+
|
|
513
|
+
box-sizing: border-box;
|
|
514
|
+
}
|
|
515
|
+
|
|
499
516
|
.form-field--rich-text .form-textarea {
|
|
500
517
|
grid-row: 2;
|
|
501
518
|
}
|
|
@@ -686,6 +703,18 @@
|
|
|
686
703
|
border-radius: var(--b4um-radius);
|
|
687
704
|
}
|
|
688
705
|
|
|
706
|
+
/* -------------------------------------------------------
|
|
707
|
+
Rich Text Attachments – responsive
|
|
708
|
+
------------------------------------------------------- */
|
|
709
|
+
|
|
710
|
+
@media (max-width: 700px) {
|
|
711
|
+
.trix-content .attachment-gallery,
|
|
712
|
+
.trix-content .attachment-gallery--2,
|
|
713
|
+
.trix-content .attachment-gallery--4 {
|
|
714
|
+
grid-template-columns: 1fr;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
689
718
|
.trix-content action-text-attachment[content-type='vnd.rubyonrails.horizontal-rule.html'] {
|
|
690
719
|
display: block;
|
|
691
720
|
width: 100%;
|
|
@@ -922,3 +951,134 @@
|
|
|
922
951
|
|
|
923
952
|
opacity: 1;
|
|
924
953
|
}
|
|
954
|
+
/* -------------------------------------------------------
|
|
955
|
+
Responsive Rich Text
|
|
956
|
+
------------------------------------------------------- */
|
|
957
|
+
|
|
958
|
+
@media (max-width: 640px) {
|
|
959
|
+
.form-field--rich-text trix-toolbar {
|
|
960
|
+
overflow: visible;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
/*
|
|
964
|
+
* Nur die Button-Zeile scrollt horizontal.
|
|
965
|
+
* Die Dialoge liegen außerhalb dieses Scrollcontainers
|
|
966
|
+
* und können deshalb vollständig sichtbar werden.
|
|
967
|
+
*/
|
|
968
|
+
.form-field--rich-text trix-toolbar .trix-button-row {
|
|
969
|
+
display: flex;
|
|
970
|
+
flex-wrap: nowrap;
|
|
971
|
+
align-items: center;
|
|
972
|
+
justify-content: flex-start;
|
|
973
|
+
|
|
974
|
+
width: 100%;
|
|
975
|
+
max-width: 100%;
|
|
976
|
+
|
|
977
|
+
gap: 4px;
|
|
978
|
+
|
|
979
|
+
overflow-x: auto;
|
|
980
|
+
overflow-y: hidden;
|
|
981
|
+
|
|
982
|
+
-webkit-overflow-scrolling: touch;
|
|
983
|
+
scrollbar-width: none;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
.form-field--rich-text trix-toolbar .trix-button-row::-webkit-scrollbar {
|
|
987
|
+
display: none;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
.form-field--rich-text trix-toolbar .trix-button-group {
|
|
991
|
+
flex: 0 0 auto;
|
|
992
|
+
|
|
993
|
+
margin: 0;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
.form-field--rich-text trix-toolbar .trix-button {
|
|
997
|
+
flex: 0 0 auto;
|
|
998
|
+
|
|
999
|
+
margin: 0;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/*
|
|
1003
|
+
* Trix-Dialoge gehören NICHT zum horizontalen
|
|
1004
|
+
* Scrollbereich der Buttons.
|
|
1005
|
+
*/
|
|
1006
|
+
.form-field--rich-text trix-toolbar .trix-dialogs {
|
|
1007
|
+
position: relative;
|
|
1008
|
+
|
|
1009
|
+
width: 100%;
|
|
1010
|
+
|
|
1011
|
+
overflow: visible;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
.form-field--rich-text trix-toolbar .trix-dialog {
|
|
1015
|
+
left: 0;
|
|
1016
|
+
right: auto;
|
|
1017
|
+
|
|
1018
|
+
max-width: 100%;
|
|
1019
|
+
|
|
1020
|
+
box-sizing: border-box;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/*
|
|
1024
|
+
* Link-Dialog nutzt auf kleinen Displays
|
|
1025
|
+
* die komplette verfügbare Toolbarbreite.
|
|
1026
|
+
*/
|
|
1027
|
+
.form-field--rich-text trix-toolbar .trix-dialog--link {
|
|
1028
|
+
width: 100%;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/*
|
|
1032
|
+
* H1–H6 bleiben kompakt nebeneinander.
|
|
1033
|
+
*/
|
|
1034
|
+
.form-field--rich-text trix-toolbar .trix-dialog--heading {
|
|
1035
|
+
width: max-content;
|
|
1036
|
+
max-width: 100%;
|
|
1037
|
+
|
|
1038
|
+
margin-left: 0;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
.form-field--rich-text trix-toolbar .trix-dialog--heading .trix-dialog__link-fields {
|
|
1042
|
+
width: auto;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.form-field--rich-text trix-toolbar .trix-dialog--heading .trix-button-group {
|
|
1046
|
+
display: flex;
|
|
1047
|
+
flex-wrap: nowrap;
|
|
1048
|
+
|
|
1049
|
+
width: auto;
|
|
1050
|
+
margin: 0;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
/*
|
|
1054
|
+
* Farbpalette ebenfalls vollständig innerhalb
|
|
1055
|
+
* der verfügbaren Breite darstellen.
|
|
1056
|
+
*/
|
|
1057
|
+
.form-field--rich-text trix-toolbar .trix-dialog--color {
|
|
1058
|
+
width: max-content;
|
|
1059
|
+
max-width: 100%;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
.form-field--rich-text trix-editor .attachment-gallery,
|
|
1063
|
+
.form-field--rich-text trix-editor .attachment-gallery--2,
|
|
1064
|
+
.form-field--rich-text trix-editor .attachment-gallery--4 {
|
|
1065
|
+
grid-template-columns: 1fr;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
.form-field--rich-text trix-toolbar .trix-button--icon {
|
|
1070
|
+
height: 1.98em;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
.form-field--rich-text trix-toolbar .trix-button-group--container-tools .trix-button {
|
|
1074
|
+
height: 2.6em;
|
|
1075
|
+
display: inline-flex;
|
|
1076
|
+
align-items: center;
|
|
1077
|
+
justify-content: center;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
@media (max-width: 768px) {
|
|
1081
|
+
trix-toolbar .trix-button--icon {
|
|
1082
|
+
height: 2em;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
@@ -48,15 +48,28 @@
|
|
|
48
48
|
.navigation__link {
|
|
49
49
|
position: relative;
|
|
50
50
|
padding: 0.5rem 0;
|
|
51
|
+
|
|
52
|
+
border: 0;
|
|
53
|
+
background: transparent;
|
|
54
|
+
|
|
51
55
|
color: var(--b4um-text);
|
|
56
|
+
font: inherit;
|
|
52
57
|
font-weight: 500;
|
|
53
58
|
text-decoration: none;
|
|
59
|
+
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
|
|
54
62
|
transition:
|
|
55
63
|
color 0.18s ease,
|
|
56
64
|
background-color 0.18s ease,
|
|
57
65
|
transform 0.18s ease;
|
|
58
66
|
}
|
|
59
67
|
|
|
68
|
+
.navigation__form {
|
|
69
|
+
margin: 0;
|
|
70
|
+
padding: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
60
73
|
.navigation__link:visited {
|
|
61
74
|
color: var(--b4um-text);
|
|
62
75
|
}
|
|
@@ -119,3 +119,21 @@
|
|
|
119
119
|
.resource-list-item:last-child {
|
|
120
120
|
border-bottom: none;
|
|
121
121
|
}
|
|
122
|
+
|
|
123
|
+
/* -------------------------------------------------------
|
|
124
|
+
Responsive resource details
|
|
125
|
+
------------------------------------------------------- */
|
|
126
|
+
|
|
127
|
+
@media (max-width: 768px) {
|
|
128
|
+
.resource-field {
|
|
129
|
+
grid-template-columns: minmax(0, 1fr);
|
|
130
|
+
row-gap: 0.5rem;
|
|
131
|
+
column-gap: 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.resource-label,
|
|
135
|
+
.resource-value {
|
|
136
|
+
min-width: 0;
|
|
137
|
+
width: 100%;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* B4UM stylesheet imports
|
|
3
|
+
*
|
|
4
|
+
* Rails 8 loads all stylesheets in app/assets/stylesheets automatically
|
|
5
|
+
* when using:
|
|
6
|
+
*
|
|
7
|
+
* <%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
|
|
8
|
+
*
|
|
9
|
+
* Therefore these imports are disabled by default.
|
|
10
|
+
* Uncomment them if your application's asset setup requires explicit imports.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/*
|
|
1
14
|
@import 'b4um/theme.css';
|
|
2
15
|
@import 'b4um/base.css';
|
|
3
16
|
@import 'b4um/layout.css';
|
|
@@ -18,3 +31,4 @@
|
|
|
18
31
|
@import 'b4um/footer.css';
|
|
19
32
|
@import 'b4um/cookie-consent.css';
|
|
20
33
|
@import 'b4um/theme-switcher.css';
|
|
34
|
+
*/
|
|
@@ -23,4 +23,17 @@ module NavigationHelper
|
|
|
23
23
|
data: { action: "click->navigation#close" }
|
|
24
24
|
)
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
def navigation_button_to(name, path, method:)
|
|
28
|
+
button_to(
|
|
29
|
+
name,
|
|
30
|
+
path,
|
|
31
|
+
method: method,
|
|
32
|
+
class: "navigation__link",
|
|
33
|
+
form: {
|
|
34
|
+
class: "navigation__form",
|
|
35
|
+
data: { action: "click->navigation#close" }
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
end
|
|
26
39
|
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "rails/generators/named_base"
|
|
5
|
+
|
|
6
|
+
module B4um
|
|
7
|
+
module Generators
|
|
8
|
+
class ReadableGenerator < Rails::Generators::NamedBase
|
|
9
|
+
argument :attribute,
|
|
10
|
+
type: :string,
|
|
11
|
+
required: true,
|
|
12
|
+
banner: "ATTRIBUTE"
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def desc(_description = nil)
|
|
16
|
+
"Adds a readable URL parameter to an existing model."
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def validate_model
|
|
21
|
+
return if File.exist?(model_path)
|
|
22
|
+
|
|
23
|
+
raise Thor::Error,
|
|
24
|
+
"Model not found: app/models/#{file_name}.rb"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def validate_attribute
|
|
28
|
+
return if model_class.column_names.include?(attribute)
|
|
29
|
+
|
|
30
|
+
raise Thor::Error,
|
|
31
|
+
"Attribute not found: #{class_name}##{attribute}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def add_readable_param
|
|
35
|
+
model_content = File.read(model_path)
|
|
36
|
+
|
|
37
|
+
if model_content.match?(/^\s*def\s+to_param\b/)
|
|
38
|
+
raise Thor::Error,
|
|
39
|
+
"#{class_name} already defines to_param."
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
inject_into_class(
|
|
43
|
+
model_path,
|
|
44
|
+
class_name,
|
|
45
|
+
<<~RUBY
|
|
46
|
+
def to_param
|
|
47
|
+
"\#{id} \#{#{attribute}}".parameterize
|
|
48
|
+
end
|
|
49
|
+
RUBY
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
say_status(
|
|
53
|
+
:readable,
|
|
54
|
+
"#{class_name} URLs now use #{attribute}",
|
|
55
|
+
:green
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def model_path
|
|
62
|
+
File.join(
|
|
63
|
+
destination_root,
|
|
64
|
+
"app/models",
|
|
65
|
+
"#{file_name}.rb"
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def model_class
|
|
70
|
+
class_name.constantize
|
|
71
|
+
rescue NameError
|
|
72
|
+
raise Thor::Error,
|
|
73
|
+
"Could not load model: #{class_name}"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -137,6 +137,64 @@ module B4um
|
|
|
137
137
|
)
|
|
138
138
|
end
|
|
139
139
|
|
|
140
|
+
def update_empty_state
|
|
141
|
+
view_file = File.join(
|
|
142
|
+
destination_root,
|
|
143
|
+
index_view_path
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
view_content = File.read(view_file)
|
|
147
|
+
|
|
148
|
+
return if view_content.include?(
|
|
149
|
+
"<% if params[:q].present? %>"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
title = file_name.pluralize.humanize.downcase
|
|
153
|
+
singular = file_name.humanize.downcase
|
|
154
|
+
|
|
155
|
+
empty_state_pattern = %r{
|
|
156
|
+
(?<indent>[ \t]*)
|
|
157
|
+
<section\ class="b4um-empty-state">\s*
|
|
158
|
+
<h2\ class="b4um-empty-state__title">\s*
|
|
159
|
+
No\ #{Regexp.escape(title)}\ yet\.\s*
|
|
160
|
+
</h2>\s*
|
|
161
|
+
<p\ class="b4um-empty-state__text">\s*
|
|
162
|
+
Create\ your\ first\ #{Regexp.escape(singular)}\ to\ get\ started\.\s*
|
|
163
|
+
</p>\s*
|
|
164
|
+
</section>
|
|
165
|
+
}x
|
|
166
|
+
|
|
167
|
+
return unless view_content.match?(empty_state_pattern)
|
|
168
|
+
|
|
169
|
+
new_empty_state = <<~ERB.chomp
|
|
170
|
+
<section class="b4um-empty-state">
|
|
171
|
+
<% if params[:q].present? %>
|
|
172
|
+
<h2 class="b4um-empty-state__title">
|
|
173
|
+
No #{title} found.
|
|
174
|
+
</h2>
|
|
175
|
+
|
|
176
|
+
<p class="b4um-empty-state__text">
|
|
177
|
+
Try a different search term.
|
|
178
|
+
</p>
|
|
179
|
+
<% else %>
|
|
180
|
+
<h2 class="b4um-empty-state__title">
|
|
181
|
+
No #{title} yet.
|
|
182
|
+
</h2>
|
|
183
|
+
|
|
184
|
+
<p class="b4um-empty-state__text">
|
|
185
|
+
Create your first #{singular} to get started.
|
|
186
|
+
</p>
|
|
187
|
+
<% end %>
|
|
188
|
+
</section>
|
|
189
|
+
ERB
|
|
190
|
+
|
|
191
|
+
gsub_file(
|
|
192
|
+
index_view_path,
|
|
193
|
+
empty_state_pattern,
|
|
194
|
+
new_empty_state
|
|
195
|
+
)
|
|
196
|
+
end
|
|
197
|
+
|
|
140
198
|
private
|
|
141
199
|
|
|
142
200
|
def model_path
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: b4um_generators
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alexander Baum
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-09-
|
|
10
|
+
date: 2026-09-28 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: railties
|
|
@@ -49,6 +49,10 @@ files:
|
|
|
49
49
|
- bin/setup
|
|
50
50
|
- lib/b4um_generators.rb
|
|
51
51
|
- lib/b4um_generators/version.rb
|
|
52
|
+
- lib/generators/b4um/attachment/attachment_generator.rb
|
|
53
|
+
- lib/generators/b4um/authentication/authentication_generator.rb
|
|
54
|
+
- lib/generators/b4um/authentication/templates/new.html.erb.tt
|
|
55
|
+
- lib/generators/b4um/authentication/templates/sessions_controller.rb.tt
|
|
52
56
|
- lib/generators/b4um/bento/bento_generator.rb
|
|
53
57
|
- lib/generators/b4um/bento/templates/_alternating.html.erb.tt
|
|
54
58
|
- lib/generators/b4um/bento/templates/_bento.html.erb.tt
|
|
@@ -104,6 +108,7 @@ files:
|
|
|
104
108
|
- lib/generators/b4um/pagination/pagination_generator.rb
|
|
105
109
|
- lib/generators/b4um/pagination/templates/_pagination.html.erb.tt
|
|
106
110
|
- lib/generators/b4um/pagination/templates/pagination.rb
|
|
111
|
+
- lib/generators/b4um/readable/readable_generator.rb
|
|
107
112
|
- lib/generators/b4um/scaffold/scaffold_generator.rb
|
|
108
113
|
- lib/generators/b4um/scaffold/templates/_bento.html.erb.tt
|
|
109
114
|
- lib/generators/b4um/scaffold/templates/_form.html.erb.tt
|