b4um_generators 0.1.0 → 0.2.7
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 +414 -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 +19 -9
- 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
|
@@ -32,6 +32,7 @@ module B4um
|
|
|
32
32
|
|
|
33
33
|
- bcrypt for password support
|
|
34
34
|
- Active Storage for image attachments
|
|
35
|
+
- Home page with root route
|
|
35
36
|
- Hero section
|
|
36
37
|
- Footer
|
|
37
38
|
- Footer sitemap
|
|
@@ -46,6 +47,38 @@ module B4um
|
|
|
46
47
|
b4um installs Active Storage and runs the database migration.
|
|
47
48
|
|
|
48
49
|
|
|
50
|
+
HOME PAGE
|
|
51
|
+
|
|
52
|
+
The installer can optionally create a home page.
|
|
53
|
+
|
|
54
|
+
During installation, b4um asks:
|
|
55
|
+
|
|
56
|
+
Create a home page? (y/n)
|
|
57
|
+
|
|
58
|
+
When selected, the controller and action can be configured:
|
|
59
|
+
|
|
60
|
+
Home controller [Pages]:
|
|
61
|
+
Home action [home]:
|
|
62
|
+
|
|
63
|
+
Press Enter to use the defaults.
|
|
64
|
+
|
|
65
|
+
With the default configuration, b4um creates:
|
|
66
|
+
|
|
67
|
+
app/controllers/pages_controller.rb
|
|
68
|
+
app/views/pages/home.html.erb
|
|
69
|
+
|
|
70
|
+
and adds:
|
|
71
|
+
|
|
72
|
+
root "pages#home"
|
|
73
|
+
|
|
74
|
+
A Home link using root_path is also added to the
|
|
75
|
+
b4um navigation.
|
|
76
|
+
|
|
77
|
+
If the application already has a root route, b4um keeps
|
|
78
|
+
the existing root route and does not add a new Home
|
|
79
|
+
navigation link.
|
|
80
|
+
|
|
81
|
+
|
|
49
82
|
HERO
|
|
50
83
|
|
|
51
84
|
The installer can add an optional hero section.
|
|
@@ -357,10 +390,10 @@ module B4um
|
|
|
357
390
|
|
|
358
391
|
READABLE URL PARAMETERS
|
|
359
392
|
|
|
360
|
-
b4um
|
|
393
|
+
b4um can generate readable URLs while keeping
|
|
361
394
|
the database ID in the URL.
|
|
362
395
|
|
|
363
|
-
|
|
396
|
+
When creating a new scaffold, use:
|
|
364
397
|
|
|
365
398
|
--param=ATTRIBUTE
|
|
366
399
|
|
|
@@ -368,15 +401,26 @@ module B4um
|
|
|
368
401
|
|
|
369
402
|
bin/rails generate b4um:scaffold Article title:string body:text --param=title
|
|
370
403
|
|
|
371
|
-
|
|
404
|
+
For an existing model, readable URLs can also be
|
|
405
|
+
added later with:
|
|
406
|
+
|
|
407
|
+
bin/rails generate b4um:readable MODEL ATTRIBUTE
|
|
408
|
+
|
|
409
|
+
Example:
|
|
410
|
+
|
|
411
|
+
bin/rails generate b4um:readable Product name
|
|
412
|
+
|
|
413
|
+
Both variants add a to_param method to the model.
|
|
414
|
+
|
|
415
|
+
Example:
|
|
372
416
|
|
|
373
417
|
def to_param
|
|
374
|
-
"\#{id} \#{
|
|
418
|
+
"\#{id} \#{name}".parameterize
|
|
375
419
|
end
|
|
376
420
|
|
|
377
421
|
Example URL:
|
|
378
422
|
|
|
379
|
-
/
|
|
423
|
+
/products/17-macbook-air
|
|
380
424
|
|
|
381
425
|
The ID remains part of the URL, so the standard Rails
|
|
382
426
|
resource lookup can still be used.
|
|
@@ -384,6 +428,14 @@ module B4um
|
|
|
384
428
|
The readable part of the URL is updated automatically
|
|
385
429
|
when the selected attribute changes.
|
|
386
430
|
|
|
431
|
+
The b4um:readable generator requires:
|
|
432
|
+
|
|
433
|
+
- An existing model
|
|
434
|
+
- An existing model attribute
|
|
435
|
+
- No existing custom to_param method
|
|
436
|
+
|
|
437
|
+
Existing to_param methods are not overwritten.
|
|
438
|
+
|
|
387
439
|
|
|
388
440
|
PASSWORDS
|
|
389
441
|
|
|
@@ -408,6 +460,113 @@ module B4um
|
|
|
408
460
|
the selected Gem automatically.
|
|
409
461
|
|
|
410
462
|
|
|
463
|
+
AUTHENTICATION
|
|
464
|
+
|
|
465
|
+
bin/rails generate b4um:authentication MODEL
|
|
466
|
+
|
|
467
|
+
Adds session-based authentication for an existing model.
|
|
468
|
+
|
|
469
|
+
Example:
|
|
470
|
+
|
|
471
|
+
bin/rails generate b4um:authentication User
|
|
472
|
+
|
|
473
|
+
The authentication model can have any name, for example:
|
|
474
|
+
|
|
475
|
+
User
|
|
476
|
+
Admin
|
|
477
|
+
Member
|
|
478
|
+
|
|
479
|
+
The selected model must:
|
|
480
|
+
|
|
481
|
+
- Already exist
|
|
482
|
+
- Use has_secure_password
|
|
483
|
+
- Have a password_digest column
|
|
484
|
+
- Use bcrypt
|
|
485
|
+
|
|
486
|
+
Authentication uses an email attribute for login.
|
|
487
|
+
|
|
488
|
+
Example:
|
|
489
|
+
|
|
490
|
+
bin/rails generate b4um:scaffold User name:string email:string password_digest:string
|
|
491
|
+
bin/rails generate b4um:authentication User
|
|
492
|
+
|
|
493
|
+
The authentication generator adds:
|
|
494
|
+
|
|
495
|
+
- Sessions controller
|
|
496
|
+
- Login form
|
|
497
|
+
- Login and logout routes
|
|
498
|
+
- Session-based current account helper
|
|
499
|
+
- logged_in? helper
|
|
500
|
+
- require_login helper
|
|
501
|
+
- Login and logout navigation controls
|
|
502
|
+
|
|
503
|
+
The generated helper name follows the selected model.
|
|
504
|
+
|
|
505
|
+
For User:
|
|
506
|
+
|
|
507
|
+
current_user
|
|
508
|
+
|
|
509
|
+
For Admin:
|
|
510
|
+
|
|
511
|
+
current_admin
|
|
512
|
+
|
|
513
|
+
Existing controllers can optionally be protected with --protect.
|
|
514
|
+
|
|
515
|
+
Example:
|
|
516
|
+
|
|
517
|
+
bin/rails generate b4um:authentication User --protect=Products
|
|
518
|
+
|
|
519
|
+
Multiple controllers can be protected in one run:
|
|
520
|
+
|
|
521
|
+
bin/rails generate b4um:authentication User --protect=Products,Articles,Comments
|
|
522
|
+
|
|
523
|
+
Protected controllers receive:
|
|
524
|
+
|
|
525
|
+
before_action :require_login, except: [:index, :show]
|
|
526
|
+
|
|
527
|
+
This keeps index and show publicly accessible while requiring
|
|
528
|
+
authentication for actions such as new, create, edit, update
|
|
529
|
+
and destroy.
|
|
530
|
+
|
|
531
|
+
For protected b4um resources, authentication also updates
|
|
532
|
+
the generated interface for logged-out visitors.
|
|
533
|
+
|
|
534
|
+
On index pages:
|
|
535
|
+
|
|
536
|
+
- New is hidden
|
|
537
|
+
|
|
538
|
+
On show pages:
|
|
539
|
+
|
|
540
|
+
- Edit is hidden
|
|
541
|
+
- Destroy is hidden
|
|
542
|
+
- Back remains visible
|
|
543
|
+
|
|
544
|
+
These controls remain available to logged-in users.
|
|
545
|
+
The controller protection remains the security boundary;
|
|
546
|
+
hiding the controls only keeps the public interface consistent.
|
|
547
|
+
|
|
548
|
+
Additional controllers can be protected later by running the
|
|
549
|
+
authentication generator again.
|
|
550
|
+
|
|
551
|
+
Example:
|
|
552
|
+
|
|
553
|
+
bin/rails generate b4um:authentication User --protect=Comments
|
|
554
|
+
|
|
555
|
+
Existing authentication helpers, routes and navigation controls
|
|
556
|
+
are not duplicated on repeated runs.
|
|
557
|
+
|
|
558
|
+
All controllers passed to --protect must already exist.
|
|
559
|
+
If a protected controller cannot be found, the generator stops
|
|
560
|
+
before changing the application.
|
|
561
|
+
|
|
562
|
+
The generator validates its requirements before changing
|
|
563
|
+
the application and reports missing authentication setup
|
|
564
|
+
with a suggested b4um scaffold command.
|
|
565
|
+
|
|
566
|
+
Repeated generator runs do not duplicate the authentication
|
|
567
|
+
helpers, routes or navigation controls.
|
|
568
|
+
|
|
569
|
+
|
|
411
570
|
ACTIVE STORAGE / IMAGES
|
|
412
571
|
|
|
413
572
|
Image attachments require Active Storage.
|
|
@@ -436,6 +595,52 @@ module B4um
|
|
|
436
595
|
|
|
437
596
|
bin/rails generate b4um:scaffold Gallery title:string images:attachments
|
|
438
597
|
|
|
598
|
+
Attachments can also be added later to an existing
|
|
599
|
+
b4um resource.
|
|
600
|
+
|
|
601
|
+
Single attachment:
|
|
602
|
+
|
|
603
|
+
bin/rails generate b4um:attachment MODEL ATTACHMENT
|
|
604
|
+
|
|
605
|
+
Example:
|
|
606
|
+
|
|
607
|
+
bin/rails generate b4um:attachment Admin avatar
|
|
608
|
+
|
|
609
|
+
This adds:
|
|
610
|
+
|
|
611
|
+
has_one_attached :avatar
|
|
612
|
+
|
|
613
|
+
Multiple attachments:
|
|
614
|
+
|
|
615
|
+
bin/rails generate b4um:attachment MODEL ATTACHMENT --multiple
|
|
616
|
+
|
|
617
|
+
Example:
|
|
618
|
+
|
|
619
|
+
bin/rails generate b4um:attachment Product images --multiple
|
|
620
|
+
|
|
621
|
+
This adds:
|
|
622
|
+
|
|
623
|
+
has_many_attached :images
|
|
624
|
+
|
|
625
|
+
When the corresponding b4um files exist, the attachment
|
|
626
|
+
generator also updates:
|
|
627
|
+
|
|
628
|
+
- The existing model
|
|
629
|
+
- The existing b4um form
|
|
630
|
+
- The controller parameters
|
|
631
|
+
- The existing b4um resource partial
|
|
632
|
+
|
|
633
|
+
Multiple attachments additionally support:
|
|
634
|
+
|
|
635
|
+
- Adding new images without replacing existing images
|
|
636
|
+
- Removing individual existing images
|
|
637
|
+
- Multiple image preview
|
|
638
|
+
- Image gallery with lightbox navigation
|
|
639
|
+
|
|
640
|
+
Repeated generator runs do not duplicate existing
|
|
641
|
+
attachment setup.
|
|
642
|
+
|
|
643
|
+
|
|
439
644
|
Image features:
|
|
440
645
|
|
|
441
646
|
- Active Storage integration
|
|
@@ -121,6 +121,37 @@ module B4um
|
|
|
121
121
|
)
|
|
122
122
|
end
|
|
123
123
|
|
|
124
|
+
def update_table_partial
|
|
125
|
+
index_content = File.read(
|
|
126
|
+
File.join(destination_root, index_view_path)
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
return unless index_content.match?(
|
|
130
|
+
/render\s+["']table["']/
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
path = File.join(
|
|
134
|
+
"app/views",
|
|
135
|
+
file_name.pluralize,
|
|
136
|
+
"_table.html.erb"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
full_path = File.join(destination_root, path)
|
|
140
|
+
|
|
141
|
+
return unless File.exist?(full_path)
|
|
142
|
+
|
|
143
|
+
content = File.read(full_path)
|
|
144
|
+
|
|
145
|
+
return if content.include?(%(<tbody id="#{plural_table_name}">))
|
|
146
|
+
return unless content.include?("<tbody>")
|
|
147
|
+
|
|
148
|
+
gsub_file(
|
|
149
|
+
path,
|
|
150
|
+
"<tbody>",
|
|
151
|
+
%(<tbody id="#{plural_table_name}">)
|
|
152
|
+
)
|
|
153
|
+
end
|
|
154
|
+
|
|
124
155
|
private
|
|
125
156
|
|
|
126
157
|
def paginated_collection
|
|
@@ -7,21 +7,32 @@ export default class extends Controller {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
connect() {
|
|
10
|
-
this.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
this.loading = false
|
|
11
|
+
this.check = this.check.bind(this)
|
|
12
|
+
|
|
13
|
+
window.addEventListener('scroll', this.check, { passive: true })
|
|
14
|
+
window.addEventListener('resize', this.check)
|
|
15
15
|
|
|
16
|
-
this.
|
|
16
|
+
this.check()
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
disconnect() {
|
|
20
|
-
this.
|
|
20
|
+
window.removeEventListener('scroll', this.check)
|
|
21
|
+
window.removeEventListener('resize', this.check)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
check() {
|
|
25
|
+
if (!this.hasNextUrlValue || !this.nextUrlValue || this.loading) return
|
|
26
|
+
|
|
27
|
+
const rect = this.element.getBoundingClientRect()
|
|
28
|
+
|
|
29
|
+
if (rect.top <= window.innerHeight + 300) {
|
|
30
|
+
this.loadMore()
|
|
31
|
+
}
|
|
21
32
|
}
|
|
22
33
|
|
|
23
34
|
async loadMore() {
|
|
24
|
-
if (!this.hasNextUrlValue || this.loading) return
|
|
35
|
+
if (!this.hasNextUrlValue || !this.nextUrlValue || this.loading) return
|
|
25
36
|
|
|
26
37
|
this.loading = true
|
|
27
38
|
|
|
@@ -51,7 +62,6 @@ export default class extends Controller {
|
|
|
51
62
|
if (nextSentinel?.dataset.infiniteScrollNextUrlValue) {
|
|
52
63
|
this.nextUrlValue = nextSentinel.dataset.infiniteScrollNextUrlValue
|
|
53
64
|
} else {
|
|
54
|
-
this.observer.disconnect()
|
|
55
65
|
this.element.remove()
|
|
56
66
|
}
|
|
57
67
|
} finally {
|
|
@@ -71,6 +71,104 @@ module B4um
|
|
|
71
71
|
say " Active Storage database tables created."
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
def install_home_page
|
|
75
|
+
unless yes?("Create a home page? (y/n)")
|
|
76
|
+
say " Home page skipped."
|
|
77
|
+
return
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
@home_controller = ask(
|
|
81
|
+
"Home controller [Pages]:"
|
|
82
|
+
).presence || "Pages"
|
|
83
|
+
|
|
84
|
+
@home_action = ask(
|
|
85
|
+
"Home action [home]:"
|
|
86
|
+
).presence || "home"
|
|
87
|
+
|
|
88
|
+
controller_name = @home_controller.underscore
|
|
89
|
+
action_name = @home_action.underscore
|
|
90
|
+
|
|
91
|
+
controller_path = File.join(
|
|
92
|
+
"app/controllers",
|
|
93
|
+
"#{controller_name}_controller.rb"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
view_path = File.join(
|
|
97
|
+
"app/views",
|
|
98
|
+
controller_name,
|
|
99
|
+
"#{action_name}.html.erb"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
full_controller_path = File.join(
|
|
103
|
+
destination_root,
|
|
104
|
+
controller_path
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
full_view_path = File.join(
|
|
108
|
+
destination_root,
|
|
109
|
+
view_path
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
unless File.exist?(full_controller_path)
|
|
113
|
+
create_file(
|
|
114
|
+
controller_path,
|
|
115
|
+
<<~RUBY
|
|
116
|
+
class #{@home_controller.camelize}Controller < ApplicationController
|
|
117
|
+
def #{action_name}
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
RUBY
|
|
121
|
+
)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
unless File.exist?(full_view_path)
|
|
125
|
+
create_file(
|
|
126
|
+
view_path,
|
|
127
|
+
<<~ERB
|
|
128
|
+
<% content_for :title, "#{action_name.humanize}" %>
|
|
129
|
+
|
|
130
|
+
<div class="page-header">
|
|
131
|
+
<h1>#{action_name.humanize}</h1>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
<div class="b4um-grid">
|
|
135
|
+
<section class="b4um-card b4um-card--full">
|
|
136
|
+
<h2 class="b4um-card__title">
|
|
137
|
+
#{action_name.humanize}
|
|
138
|
+
</h2>
|
|
139
|
+
|
|
140
|
+
<p class="b4um-card__text">
|
|
141
|
+
Add your content here.
|
|
142
|
+
</p>
|
|
143
|
+
</section>
|
|
144
|
+
</div>
|
|
145
|
+
ERB
|
|
146
|
+
)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
routes_path = File.join(
|
|
150
|
+
destination_root,
|
|
151
|
+
"config/routes.rb"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
routes = File.read(routes_path)
|
|
155
|
+
|
|
156
|
+
if routes.match?(/^\s*root\b/)
|
|
157
|
+
say " Root route already exists; keeping existing root route."
|
|
158
|
+
@home_navigation_enabled = false
|
|
159
|
+
else
|
|
160
|
+
route(
|
|
161
|
+
%(root "#{controller_name}##{action_name}")
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
@home_navigation_enabled = true
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
@home_page_installed = true
|
|
168
|
+
|
|
169
|
+
say " Home page installed."
|
|
170
|
+
end
|
|
171
|
+
|
|
74
172
|
def create_stylesheet
|
|
75
173
|
copy_file "b4um.css", "app/assets/stylesheets/b4um.css"
|
|
76
174
|
|
|
@@ -190,8 +288,49 @@ module B4um
|
|
|
190
288
|
end
|
|
191
289
|
|
|
192
290
|
def copy_navigation
|
|
291
|
+
navigation_path = "app/views/shared/_navigation.html.erb"
|
|
292
|
+
|
|
193
293
|
copy_file "_navigation.html.erb",
|
|
194
|
-
|
|
294
|
+
navigation_path
|
|
295
|
+
|
|
296
|
+
return unless @home_page_installed
|
|
297
|
+
return unless @home_navigation_enabled
|
|
298
|
+
|
|
299
|
+
full_navigation_path = File.join(
|
|
300
|
+
destination_root,
|
|
301
|
+
navigation_path
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
navigation = File.read(full_navigation_path)
|
|
305
|
+
marker = "<%# B4UM_NAVIGATION_LINKS %>"
|
|
306
|
+
|
|
307
|
+
return unless navigation.include?(marker)
|
|
308
|
+
|
|
309
|
+
controller_name = @home_controller.underscore
|
|
310
|
+
action_name = @home_action.underscore
|
|
311
|
+
|
|
312
|
+
return if navigation.include?("root_path")
|
|
313
|
+
|
|
314
|
+
indented_marker = " #{marker}"
|
|
315
|
+
|
|
316
|
+
home_link = <<~ERB.chomp
|
|
317
|
+
<%= navigation_link_to "#{action_name.humanize}",
|
|
318
|
+
root_path,
|
|
319
|
+
controller: :#{controller_name},
|
|
320
|
+
action: :#{action_name} %>
|
|
321
|
+
|
|
322
|
+
#{marker}
|
|
323
|
+
ERB
|
|
324
|
+
|
|
325
|
+
indented_home_link = home_link.lines.map do |line|
|
|
326
|
+
line.strip.empty? ? line : " #{line}"
|
|
327
|
+
end.join
|
|
328
|
+
|
|
329
|
+
gsub_file(
|
|
330
|
+
navigation_path,
|
|
331
|
+
indented_marker,
|
|
332
|
+
indented_home_link
|
|
333
|
+
)
|
|
195
334
|
end
|
|
196
335
|
|
|
197
336
|
def copy_navigation_controller
|
|
@@ -366,7 +505,7 @@ module B4um
|
|
|
366
505
|
'<main class="container">',
|
|
367
506
|
<<~ERB.chomp
|
|
368
507
|
<main class="container">
|
|
369
|
-
<%= render "shared/hero" if request.path == root_path %>
|
|
508
|
+
<%= render "shared/hero" if respond_to?(:root_path) && request.path == root_path %>
|
|
370
509
|
ERB
|
|
371
510
|
)
|
|
372
511
|
end
|
|
@@ -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
|
+
}
|