rails_app_generator 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/after_templates/rag_tailwind.rb +2 -4
- data/after_templates/rag_tailwind_daisyui/index.html.erb +181 -0
- data/after_templates/rag_tailwind_daisyui.rb +25 -0
- data/after_templates/rag_tailwind_hotwire_form/_contact.html.erb +8 -0
- data/after_templates/rag_tailwind_hotwire_form/_count.html.erb +1 -0
- data/after_templates/rag_tailwind_hotwire_form/_flash.html.erb +6 -0
- data/after_templates/rag_tailwind_hotwire_form/_form.html.erb +16 -0
- data/after_templates/rag_tailwind_hotwire_form/_list.html.erb +19 -0
- data/after_templates/rag_tailwind_hotwire_form/application.html.erb +24 -0
- data/after_templates/rag_tailwind_hotwire_form/application.js +30 -0
- data/after_templates/rag_tailwind_hotwire_form/application.tailwind.css +111 -0
- data/after_templates/rag_tailwind_hotwire_form/application_helper.rb +15 -0
- data/after_templates/rag_tailwind_hotwire_form/contact.rb +5 -0
- data/after_templates/rag_tailwind_hotwire_form/contacts_controller.rb +98 -0
- data/after_templates/rag_tailwind_hotwire_form/create.turbo_stream.erb +4 -0
- data/after_templates/rag_tailwind_hotwire_form/edit.html.erb +12 -0
- data/after_templates/rag_tailwind_hotwire_form/index.html.erb +5 -0
- data/after_templates/rag_tailwind_hotwire_form/new.html.erb +12 -0
- data/after_templates/rag_tailwind_hotwire_form/show.html.erb +16 -0
- data/after_templates/rag_tailwind_hotwire_form/update.turbo_stream.erb +2 -0
- data/after_templates/rag_tailwind_hotwire_form.rb +54 -0
- data/lib/rails_app_generator/app_generator.rb +21 -0
- data/lib/rails_app_generator/diff/open_in_editor.rb +1 -1
- data/lib/rails_app_generator/diff/processor.rb +7 -1
- data/lib/rails_app_generator/version.rb +1 -1
- data/package-lock.json +1019 -85
- data/package.json +4 -1
- data/profiles/rag-tailwind-daisyui.json +10 -0
- data/profiles/rag-tailwind-hotwire-form.json +13 -0
- metadata +24 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1b9515cc01763f710f8f7461e0d8166d5192771ed45267be53c399fa4d0f9c8
|
4
|
+
data.tar.gz: c2c4069a59328153fcab6e5f81c78e39f58a11f759103dda01d0c74571611ea5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3576c0c56cb8efaf50aab437e827a5e8ef973107537b9ae5f8362d91426161d0382b2bc463bae598419af396740eed71ba6720585b4d085f47051b64c3b0d4a0
|
7
|
+
data.tar.gz: 84ee7ac005aa6715de7697ccc8d0a2650f9d49d6dff1bbbc4d0e71ce51337ebe185449612fd3ec4204623f9fed3571427f1f028c3c7e4426d8d1f96b68ccead1
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## [0.1.2](https://github.com/klueless-io/rails_app_generator/compare/v0.1.1...v0.1.2) (2022-07-26)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* add profile tailwind_hotwire ([b79bb70](https://github.com/klueless-io/rails_app_generator/commit/b79bb70258c7e312d460961dd98516ddd1e2650c))
|
7
|
+
* add profile tailwind_hotwire ([c9ac471](https://github.com/klueless-io/rails_app_generator/commit/c9ac471e4391fe0ddd4b97977916da25cdc4f33e))
|
8
|
+
|
1
9
|
## [0.1.1](https://github.com/klueless-io/rails_app_generator/compare/v0.1.0...v0.1.1) (2022-07-26)
|
2
10
|
|
3
11
|
|
@@ -16,16 +16,13 @@ add_controller('home', 'index', 'about')
|
|
16
16
|
route("root 'home#index'")
|
17
17
|
|
18
18
|
index_content = join_templates(
|
19
|
-
'component-section-begin.html',
|
20
19
|
'component-nav.html',
|
21
20
|
'component-hero.html',
|
22
21
|
'component-cta.html',
|
23
22
|
'component-faq.html',
|
24
23
|
'component-cta.html',
|
25
|
-
'component-footer.html'
|
26
|
-
'component-section-end.html'
|
24
|
+
'component-footer.html'
|
27
25
|
)
|
28
|
-
# join: "</section>\n\n<section>\n"
|
29
26
|
|
30
27
|
create_file 'app/views/home/index.html.erb', index_content, force: true
|
31
28
|
|
@@ -48,6 +45,7 @@ end
|
|
48
45
|
|
49
46
|
def add_css_customizations
|
50
47
|
# Update the manifest to include the stylesheets
|
48
|
+
# IS THIS CONFIGURED?
|
51
49
|
append_to_file 'app/assets/config/manifest.js' , read_template('manifest.js')
|
52
50
|
|
53
51
|
# This is how you would add custom styling via @import in the application.bootstrap.css
|
@@ -0,0 +1,181 @@
|
|
1
|
+
<div class="lg:flex lg:items-center lg:justify-between">
|
2
|
+
<div class="flex-1 min-w-0">
|
3
|
+
<h2 class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:truncate">Regular Tailwind CSS</h2>
|
4
|
+
<div class="mt-1 flex flex-col sm:flex-row sm:flex-wrap sm:mt-0 sm:space-x-6">
|
5
|
+
<div class="mt-2 flex items-center text-sm text-gray-500">
|
6
|
+
<!-- Heroicon name: solid/briefcase -->
|
7
|
+
<svg class="flex-shrink-0 mr-1.5 h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
8
|
+
<path fill-rule="evenodd" d="M6 6V5a3 3 0 013-3h2a3 3 0 013 3v1h2a2 2 0 012 2v3.57A22.952 22.952 0 0110 13a22.95 22.95 0 01-8-1.43V8a2 2 0 012-2h2zm2-1a1 1 0 011-1h2a1 1 0 011 1v1H8V5zm1 5a1 1 0 011-1h.01a1 1 0 110 2H10a1 1 0 01-1-1z" clip-rule="evenodd" />
|
9
|
+
<path d="M2 13.692V16a2 2 0 002 2h12a2 2 0 002-2v-2.308A24.974 24.974 0 0110 15c-2.796 0-5.487-.46-8-1.308z" />
|
10
|
+
</svg>
|
11
|
+
Full-time
|
12
|
+
</div>
|
13
|
+
<div class="mt-2 flex items-center text-sm text-gray-500">
|
14
|
+
<!-- Heroicon name: solid/location-marker -->
|
15
|
+
<svg class="flex-shrink-0 mr-1.5 h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
16
|
+
<path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd" />
|
17
|
+
</svg>
|
18
|
+
Remote
|
19
|
+
</div>
|
20
|
+
<div class="mt-2 flex items-center text-sm text-gray-500">
|
21
|
+
<!-- Heroicon name: solid/currency-dollar -->
|
22
|
+
<svg class="flex-shrink-0 mr-1.5 h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
23
|
+
<path d="M8.433 7.418c.155-.103.346-.196.567-.267v1.698a2.305 2.305 0 01-.567-.267C8.07 8.34 8 8.114 8 8c0-.114.07-.34.433-.582zM11 12.849v-1.698c.22.071.412.164.567.267.364.243.433.468.433.582 0 .114-.07.34-.433.582a2.305 2.305 0 01-.567.267z" />
|
24
|
+
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-13a1 1 0 10-2 0v.092a4.535 4.535 0 00-1.676.662C6.602 6.234 6 7.009 6 8c0 .99.602 1.765 1.324 2.246.48.32 1.054.545 1.676.662v1.941c-.391-.127-.68-.317-.843-.504a1 1 0 10-1.51 1.31c.562.649 1.413 1.076 2.353 1.253V15a1 1 0 102 0v-.092a4.535 4.535 0 001.676-.662C13.398 13.766 14 12.991 14 12c0-.99-.602-1.765-1.324-2.246A4.535 4.535 0 0011 9.092V7.151c.391.127.68.317.843.504a1 1 0 101.511-1.31c-.563-.649-1.413-1.076-2.354-1.253V5z" clip-rule="evenodd" />
|
25
|
+
</svg>
|
26
|
+
$120k – $140k
|
27
|
+
</div>
|
28
|
+
<div class="mt-2 flex items-center text-sm text-gray-500">
|
29
|
+
<!-- Heroicon name: solid/calendar -->
|
30
|
+
<svg class="flex-shrink-0 mr-1.5 h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
31
|
+
<path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd" />
|
32
|
+
</svg>
|
33
|
+
Closing on January 9, 2020
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
<div class="mt-5 flex lg:mt-0 lg:ml-4">
|
38
|
+
<span class="hidden sm:block">
|
39
|
+
<button type="button" class="inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
|
40
|
+
<!-- Heroicon name: solid/pencil -->
|
41
|
+
<svg class="-ml-1 mr-2 h-5 w-5 text-gray-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
42
|
+
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
|
43
|
+
</svg>
|
44
|
+
Edit
|
45
|
+
</button>
|
46
|
+
</span>
|
47
|
+
|
48
|
+
<span class="hidden sm:block ml-3">
|
49
|
+
<button type="button" class="inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
|
50
|
+
<!-- Heroicon name: solid/link -->
|
51
|
+
<svg class="-ml-1 mr-2 h-5 w-5 text-gray-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
52
|
+
<path fill-rule="evenodd" d="M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z" clip-rule="evenodd" />
|
53
|
+
</svg>
|
54
|
+
View
|
55
|
+
</button>
|
56
|
+
</span>
|
57
|
+
|
58
|
+
<span class="sm:ml-3">
|
59
|
+
<button type="button" class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
|
60
|
+
<!-- Heroicon name: solid/check -->
|
61
|
+
<svg class="-ml-1 mr-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
62
|
+
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
|
63
|
+
</svg>
|
64
|
+
Publish
|
65
|
+
</button>
|
66
|
+
</span>
|
67
|
+
|
68
|
+
<!-- Dropdown -->
|
69
|
+
<div class="ml-3 relative sm:hidden">
|
70
|
+
<button type="button" class="inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" id="mobile-menu-button" aria-expanded="false" aria-haspopup="true">
|
71
|
+
More
|
72
|
+
<!-- Heroicon name: solid/chevron-down -->
|
73
|
+
<svg class="-mr-1 ml-2 h-5 w-5 text-gray-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
74
|
+
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
|
75
|
+
</svg>
|
76
|
+
</button>
|
77
|
+
|
78
|
+
<!--
|
79
|
+
Dropdown menu, show/hide based on menu state.
|
80
|
+
|
81
|
+
Entering: "transition ease-out duration-200"
|
82
|
+
From: "transform opacity-0 scale-95"
|
83
|
+
To: "transform opacity-100 scale-100"
|
84
|
+
Leaving: "transition ease-in duration-75"
|
85
|
+
From: "transform opacity-100 scale-100"
|
86
|
+
To: "transform opacity-0 scale-95"
|
87
|
+
-->
|
88
|
+
<div class="origin-top-right absolute right-0 mt-2 -mr-1 w-48 rounded-md shadow-lg py-1 bg-white ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="mobile-menu-button" tabindex="-1">
|
89
|
+
<!-- Active: "bg-gray-100", Not Active: "" -->
|
90
|
+
<a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="mobile-menu-item-0">Edit</a>
|
91
|
+
<a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="mobile-menu-item-1">View</a>
|
92
|
+
</div>
|
93
|
+
</div>
|
94
|
+
</div>
|
95
|
+
</div>
|
96
|
+
|
97
|
+
<br>
|
98
|
+
<hr>
|
99
|
+
<br>
|
100
|
+
|
101
|
+
<div class="navbar bg-base-100">
|
102
|
+
<div class="flex-1">
|
103
|
+
<a class="btn btn-ghost normal-case text-2xl font-bold text-gray-900 sm:text-3xl">DaisyUI Tailwind CSS</a>
|
104
|
+
</div>
|
105
|
+
<div class="flex-none">
|
106
|
+
<ul class="menu menu-horizontal p-0">
|
107
|
+
<li><a>Item 1</a></li>
|
108
|
+
<li tabindex="0">
|
109
|
+
<a>
|
110
|
+
Parent
|
111
|
+
<svg class="fill-current" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z"/></svg>
|
112
|
+
</a>
|
113
|
+
<ul class="p-2 bg-base-100">
|
114
|
+
<li><a>Submenu 1</a></li>
|
115
|
+
<li><a>Submenu 2</a></li>
|
116
|
+
</ul>
|
117
|
+
</li>
|
118
|
+
<li><a>Item 3</a></li>
|
119
|
+
</ul>
|
120
|
+
</div>
|
121
|
+
</div>
|
122
|
+
|
123
|
+
<div class="hero bg-base-200">
|
124
|
+
<div class="hero-content flex-col lg:flex-row-reverse">
|
125
|
+
<img src="https://placeimg.com/260/400/arch" class="max-w-sm rounded-lg shadow-2xl" />
|
126
|
+
<div>
|
127
|
+
<h1 class="text-5xl font-bold">Box Office News!</h1>
|
128
|
+
<p class="py-6">Provident cupiditate voluptatem et in. Quaerat fugiat ut assumenda excepturi exercitationem quasi. In deleniti eaque aut repudiandae et a id nisi.</p>
|
129
|
+
<button class="btn btn-primary">Get Started</button>
|
130
|
+
</div>
|
131
|
+
</div>
|
132
|
+
</div>
|
133
|
+
|
134
|
+
<div class="grid grid-cols-4 gap-4 m-8">
|
135
|
+
<div class="card w-96 bg-base-100 shadow-xl">
|
136
|
+
<div class="card-body">
|
137
|
+
<h2 class="card-title">Shoes!</h2>
|
138
|
+
<p>If a dog chews shoes whose shoes does he choose?</p>
|
139
|
+
</div>
|
140
|
+
<figure><img src="https://placeimg.com/400/225/arch" alt="Shoes" /></figure>
|
141
|
+
</div>
|
142
|
+
<div class="card w-96 bg-base-100 shadow-xl">
|
143
|
+
<div class="card-body">
|
144
|
+
<h2 class="card-title">Shoes!</h2>
|
145
|
+
<p>If a dog chews shoes whose shoes does he choose?</p>
|
146
|
+
</div>
|
147
|
+
<figure><img src="https://placeimg.com/400/225/arch" alt="Shoes" /></figure>
|
148
|
+
</div>
|
149
|
+
<div class="card w-96 bg-base-100 shadow-xl">
|
150
|
+
<div class="card-body">
|
151
|
+
<h2 class="card-title">Shoes!</h2>
|
152
|
+
<p>If a dog chews shoes whose shoes does he choose?</p>
|
153
|
+
</div>
|
154
|
+
<figure><img src="https://placeimg.com/400/225/arch" alt="Shoes" /></figure>
|
155
|
+
</div>
|
156
|
+
<div class="card w-96 bg-base-100 shadow-xl">
|
157
|
+
<div class="card-body">
|
158
|
+
<h2 class="card-title">Shoes!</h2>
|
159
|
+
<p>If a dog chews shoes whose shoes does he choose?</p>
|
160
|
+
</div>
|
161
|
+
<figure><img src="https://placeimg.com/400/225/arch" alt="Shoes" /></figure>
|
162
|
+
</div>
|
163
|
+
</div>
|
164
|
+
|
165
|
+
<footer class="footer footer-center p-10 bg-primary text-primary-content">
|
166
|
+
<div>
|
167
|
+
<svg width="50" height="50" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" class="inline-block fill-current"><path d="M22.672 15.226l-2.432.811.841 2.515c.33 1.019-.209 2.127-1.23 2.456-1.15.325-2.148-.321-2.463-1.226l-.84-2.518-5.013 1.677.84 2.517c.391 1.203-.434 2.542-1.831 2.542-.88 0-1.601-.564-1.86-1.314l-.842-2.516-2.431.809c-1.135.328-2.145-.317-2.463-1.229-.329-1.018.211-2.127 1.231-2.456l2.432-.809-1.621-4.823-2.432.808c-1.355.384-2.558-.59-2.558-1.839 0-.817.509-1.582 1.327-1.846l2.433-.809-.842-2.515c-.33-1.02.211-2.129 1.232-2.458 1.02-.329 2.13.209 2.461 1.229l.842 2.515 5.011-1.677-.839-2.517c-.403-1.238.484-2.553 1.843-2.553.819 0 1.585.509 1.85 1.326l.841 2.517 2.431-.81c1.02-.33 2.131.211 2.461 1.229.332 1.018-.21 2.126-1.23 2.456l-2.433.809 1.622 4.823 2.433-.809c1.242-.401 2.557.484 2.557 1.838 0 .819-.51 1.583-1.328 1.847m-8.992-6.428l-5.01 1.675 1.619 4.828 5.011-1.674-1.62-4.829z"></path></svg>
|
168
|
+
<p class="font-bold">
|
169
|
+
ACME Industries Ltd. <br>Providing reliable tech since 1992
|
170
|
+
</p>
|
171
|
+
<p>Copyright © 2022 - All right reserved</p>
|
172
|
+
</div>
|
173
|
+
<div>
|
174
|
+
<div class="grid grid-flow-col gap-4">
|
175
|
+
<a><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="fill-current"><path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"></path></svg></a>
|
176
|
+
<a><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="fill-current"><path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"></path></svg></a>
|
177
|
+
<a><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="fill-current"><path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"></path></svg></a>
|
178
|
+
</div>
|
179
|
+
</div>
|
180
|
+
</footer>
|
181
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Daisy
|
4
|
+
require 'pry'
|
5
|
+
|
6
|
+
# Do NOT use the --css=tailwind option when using DaisyUI or any other custom plugin syste for tailwindcss
|
7
|
+
|
8
|
+
self.local_template_path = File.join(File.dirname(__FILE__), 'rag_tailwind_daisyui')
|
9
|
+
|
10
|
+
gac 'base rails 7 image created'
|
11
|
+
|
12
|
+
add_controller('home', 'index')
|
13
|
+
route("root 'home#index'")
|
14
|
+
|
15
|
+
template 'index.html.erb', 'app/views/home/index.html.erb' , force: true
|
16
|
+
|
17
|
+
after_bundle do
|
18
|
+
gem "cssbundling-rails"
|
19
|
+
|
20
|
+
rails_command('css:install:tailwind')
|
21
|
+
run('npm install daisyui')
|
22
|
+
|
23
|
+
gsub_file 'tailwind.config.js', %(]\n}), "],\n plugins: [require(\"daisyui\")],\n}"
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<tr id="<%= dom_id(contact) %>" data-stream-enter-class="animate-item-in" data-stream-exit-class="animate-item-out">
|
2
|
+
<td><%= contact.id %></td>
|
3
|
+
<td><%= link_to contact.name, contact_path(contact), data: { turbo_frame: "_top" } %></td>
|
4
|
+
<td><%= contact.age %></td>
|
5
|
+
<td><%= contact.email %></td>
|
6
|
+
<td><%= link_to "Edit", edit_contact_path(contact), class: "btn btn-link btn-sm", data: { turbo_frame: "_top" } %></td>
|
7
|
+
<td><%= button_to "Delete", contact_path(contact), method: :delete, class: "btn btn-link btn-sm" %></td>
|
8
|
+
</tr>
|
@@ -0,0 +1 @@
|
|
1
|
+
<span data-stream-enter-class="animate-item-in" data-stream-exit-class="animate-item-out">Showing <%= contacts.length %> <%= "contact".pluralize(contacts.length) %></span>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<%= form_for contact do |f| %>
|
2
|
+
<% if contact.errors.any? %>
|
3
|
+
<div class="form-errors">
|
4
|
+
<div class="alert shadow-lg alert-error text-white">
|
5
|
+
Your form's got some errors
|
6
|
+
</div>
|
7
|
+
</div>
|
8
|
+
<% end %>
|
9
|
+
<%= f.text_field :name, placeholder: "Your first name", class: "input input-bordered w-full max-w-xs my-5" %>
|
10
|
+
<%= inline_error_for(:name, contact) %>
|
11
|
+
<%= f.text_field :age, placeholder: "Your age", class: "input input-bordered w-full max-w-xs my-4" %>
|
12
|
+
<%= inline_error_for(:age, contact) %>
|
13
|
+
<%= f.text_field :email, placeholder: "Your email address", class: "input input-bordered w-full max-w-xs my-4" %>
|
14
|
+
<%= inline_error_for(:email, contact) %>
|
15
|
+
<%= f.submit "Save", class: "form-control btn btn-primary my-4" %>
|
16
|
+
<% end %>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<table class="table table-zebra mt-0 w-full">
|
2
|
+
<thead>
|
3
|
+
<tr class="w-full">
|
4
|
+
<th class="text-left">ID</th>
|
5
|
+
<th class="text-left">Name</th>
|
6
|
+
<th class="text-left">Age</th>
|
7
|
+
<th class="text-left">Email</th>
|
8
|
+
<th class="text-center" colspan="2">Actions</th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<tbody id="contacts-list" data-controller="contacts" data-action="">
|
12
|
+
<% contacts.each do |contact| %>
|
13
|
+
<%= render partial: "contact", locals: { contact: contact } %>
|
14
|
+
<% end %>
|
15
|
+
</tbody>
|
16
|
+
</table>
|
17
|
+
<div class="text-gray-400 mt-4 text-xs text-right" id="contacts-count">
|
18
|
+
<%= render partial: "count", locals: { contacts: contacts } %>
|
19
|
+
</div>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html data-theme="emerald">
|
3
|
+
<head>
|
4
|
+
<title>TailwindHotwireForm</title>
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
|
+
<%= csrf_meta_tags %>
|
7
|
+
<%= csp_meta_tag %>
|
8
|
+
<%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
|
9
|
+
|
10
|
+
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
|
11
|
+
<%= javascript_importmap_tags %>
|
12
|
+
</head>
|
13
|
+
|
14
|
+
<body>
|
15
|
+
<main class="container mx-auto">
|
16
|
+
<div class="py-8">
|
17
|
+
<div id="flash" class="flash">
|
18
|
+
<%= render partial: "shared/flash" %>
|
19
|
+
</div>
|
20
|
+
<%= yield %>
|
21
|
+
</div>
|
22
|
+
</main>
|
23
|
+
</body>
|
24
|
+
</html>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
|
2
|
+
import "@hotwired/turbo-rails"
|
3
|
+
import "controllers"
|
4
|
+
|
5
|
+
document.addEventListener("turbo:before-stream-render", function(event) {
|
6
|
+
// Add a class to an element we are about to add to the page
|
7
|
+
// as defined by its "data-stream-enter-class"
|
8
|
+
if (event.target.firstElementChild instanceof HTMLTemplateElement) {
|
9
|
+
var enterAnimationClass = event.target.templateContent.firstElementChild.dataset.streamEnterClass
|
10
|
+
if (enterAnimationClass) {
|
11
|
+
event.target.templateElement.content.firstElementChild.classList.add(enterAnimationClass)
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
// Add a class to an element we are about to remove from the page
|
16
|
+
// as defined by its "data-stream-exit-class"
|
17
|
+
var elementToRemove = document.getElementById(event.target.target)
|
18
|
+
if (elementToRemove) {
|
19
|
+
var streamExitClass = elementToRemove.dataset.streamExitClass
|
20
|
+
if (streamExitClass) {
|
21
|
+
// Intercept the removal of the element
|
22
|
+
event.preventDefault()
|
23
|
+
elementToRemove.classList.add(streamExitClass)
|
24
|
+
// Wait for its animation to end before removing the element
|
25
|
+
elementToRemove.addEventListener("animationend", function() {
|
26
|
+
event.target.performAction()
|
27
|
+
})
|
28
|
+
}
|
29
|
+
}
|
30
|
+
})
|
@@ -0,0 +1,111 @@
|
|
1
|
+
@tailwind base;
|
2
|
+
@tailwind components;
|
3
|
+
@tailwind utilities;
|
4
|
+
|
5
|
+
/*
|
6
|
+
|
7
|
+
@layer components {
|
8
|
+
.btn-primary {
|
9
|
+
@apply py-2 px-4 bg-blue-200;
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
*/
|
14
|
+
|
15
|
+
html {
|
16
|
+
font-size: 20px
|
17
|
+
}
|
18
|
+
|
19
|
+
.form-errors {
|
20
|
+
color: red;
|
21
|
+
}
|
22
|
+
|
23
|
+
.field_with_errors .input-bordered {
|
24
|
+
border: 1px solid red;
|
25
|
+
margin-bottom: 0;
|
26
|
+
}
|
27
|
+
|
28
|
+
/* Animation */
|
29
|
+
/* */
|
30
|
+
/* Got it from here: */
|
31
|
+
/* https://edforshaw.co.uk/hotwire-turbo-stream-animations */
|
32
|
+
/* and here: */
|
33
|
+
/* https://stackoverflow.com/a/61306871/4072276 */
|
34
|
+
|
35
|
+
.animate-in {
|
36
|
+
animation: slide-in 0.25s ease-out;
|
37
|
+
}
|
38
|
+
|
39
|
+
.animate-out {
|
40
|
+
animation: slide-out 0.25s ease-out;
|
41
|
+
}
|
42
|
+
|
43
|
+
@keyframes slide-in {
|
44
|
+
from { transform: translateX(4rem); }
|
45
|
+
to { transform: translateX(0); }
|
46
|
+
}
|
47
|
+
|
48
|
+
@keyframes slide-out {
|
49
|
+
from { transform: translateX(0); }
|
50
|
+
to { transform: translateX(4rem); }
|
51
|
+
}
|
52
|
+
|
53
|
+
.animate-item-in {
|
54
|
+
transition-duration: 0.25s;
|
55
|
+
animation: addRow 0.25s ease-in;
|
56
|
+
transform-origin: top;
|
57
|
+
}
|
58
|
+
|
59
|
+
.animate-item-out {
|
60
|
+
transition-duration: 0.25s;
|
61
|
+
animation: removeRow 0.25s ease-in;
|
62
|
+
transform-origin: bottom;
|
63
|
+
}
|
64
|
+
|
65
|
+
@keyframes addRow {
|
66
|
+
0% {
|
67
|
+
transform: scale(1, 0);
|
68
|
+
line-height: 0px;
|
69
|
+
background-color: #fff;
|
70
|
+
visibility: collapse;
|
71
|
+
}
|
72
|
+
50% {
|
73
|
+
transform: scale(1, 1);
|
74
|
+
line-height: 20px;
|
75
|
+
visibility: visible;
|
76
|
+
}
|
77
|
+
100% {
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
@keyframes removeRow {
|
82
|
+
100% {
|
83
|
+
transform: scale(1, 1);
|
84
|
+
line-height: 20px;
|
85
|
+
visibility: visible;
|
86
|
+
}
|
87
|
+
50% {
|
88
|
+
transform: scale(1, 0);
|
89
|
+
line-height: 0px;
|
90
|
+
background-color: #fff;
|
91
|
+
visibility: collapse;
|
92
|
+
}
|
93
|
+
0% {
|
94
|
+
}
|
95
|
+
}
|
96
|
+
.flash {
|
97
|
+
height: 70px;
|
98
|
+
margin-bottom: 2rem;
|
99
|
+
}
|
100
|
+
|
101
|
+
.alert-success {
|
102
|
+
--tw-bg-opacity: 1;
|
103
|
+
background-color: hsl(var(--su)/var(--tw-bg-opacity));
|
104
|
+
--tw-text-opacity: 1;
|
105
|
+
color: hsl(var(--suc,var(--nc))/var(--tw-text-opacity));
|
106
|
+
}
|
107
|
+
|
108
|
+
.text-white {
|
109
|
+
--tw-text-opacity: 1;
|
110
|
+
color: rgb(255 255 255/var(--tw-text-opacity));
|
111
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ApplicationHelper
|
2
|
+
|
3
|
+
def inline_error_for(field, form_obj)
|
4
|
+
html = []
|
5
|
+
|
6
|
+
if form_obj.errors[field].any?
|
7
|
+
html << form_obj.errors[field].map do |msg|
|
8
|
+
tag.div(msg, class: "text-red-400 text-xs m-0 p-0 text-right mb-2")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
html.join.html_safe
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
class Contact < ApplicationRecord
|
2
|
+
validates :name, presence: true
|
3
|
+
validates :age, presence: true, numericality: true, inclusion: { in: 20...100, message: "must be between 20 and 100" }
|
4
|
+
validates :email, presence: true, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
|
5
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
class ContactsController < ApplicationController
|
2
|
+
include ActionView::RecordIdentifier
|
3
|
+
|
4
|
+
before_action :set_contact, only: %i[show edit update destroy]
|
5
|
+
before_action :all_contacts #, except: [:new, :create, :index]
|
6
|
+
|
7
|
+
# GET /contacts or /contacts.json
|
8
|
+
def index
|
9
|
+
end
|
10
|
+
|
11
|
+
# GET /contacts/1 or /contacts/1.json
|
12
|
+
def show
|
13
|
+
end
|
14
|
+
|
15
|
+
# GET /contacts/new
|
16
|
+
def new
|
17
|
+
@contact = Contact.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# GET /contacts/1/edit
|
21
|
+
def edit
|
22
|
+
end
|
23
|
+
|
24
|
+
# POST /contacts or /contacts.json
|
25
|
+
def create
|
26
|
+
@contact = Contact.new(contact_params)
|
27
|
+
|
28
|
+
if @contact.save
|
29
|
+
flash[:notice] = 'Contact was successfully created.'
|
30
|
+
else
|
31
|
+
render :new, status: :unprocessable_entity
|
32
|
+
end
|
33
|
+
# respond_to do |format|
|
34
|
+
# if @contact.save
|
35
|
+
# format.html { redirect_to contact_url(@contact), notice: "Contact was successfully created." }
|
36
|
+
# format.json { render :show, status: :created, location: @contact }
|
37
|
+
# else
|
38
|
+
# format.html { render :new, status: :unprocessable_entity }
|
39
|
+
# format.json { render json: @contact.errors, status: :unprocessable_entity }
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
end
|
43
|
+
|
44
|
+
# PATCH/PUT /contacts/1 or /contacts/1.json
|
45
|
+
def update
|
46
|
+
if @contact.update(contact_params)
|
47
|
+
flash[:notice] = "Contact updated"
|
48
|
+
else
|
49
|
+
render :edit, status: :unprocessable_entity
|
50
|
+
end
|
51
|
+
# respond_to do |format|
|
52
|
+
# if @contact.update(contact_params)
|
53
|
+
# format.html { redirect_to contact_url(@contact), notice: "Contact was successfully updated." }
|
54
|
+
# format.json { render :show, status: :ok, location: @contact }
|
55
|
+
# else
|
56
|
+
# format.html { render :edit, status: :unprocessable_entity }
|
57
|
+
# format.json { render json: @contact.errors, status: :unprocessable_entity }
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
end
|
61
|
+
|
62
|
+
# DELETE /contacts/1 or /contacts/1.json
|
63
|
+
# def destroy
|
64
|
+
# @contact.destroy
|
65
|
+
|
66
|
+
# respond_to do |format|
|
67
|
+
# format.html { redirect_to contacts_url, notice: "Contact was successfully destroyed." }
|
68
|
+
# format.json { head :no_content }
|
69
|
+
# end
|
70
|
+
# end
|
71
|
+
def destroy
|
72
|
+
@contact.destroy
|
73
|
+
flash[:notice] = "Contact removed"
|
74
|
+
render turbo_stream: [
|
75
|
+
turbo_stream.update("flash", partial: "shared/flash"),
|
76
|
+
turbo_stream.remove(dom_id(@contact)),
|
77
|
+
turbo_stream.update("contacts-count", partial: "contacts/count", locals: { contacts: @contacts })
|
78
|
+
]
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
# Use callbacks to share common setup or constraints between actions.
|
83
|
+
def set_contact
|
84
|
+
@contact = Contact.find(params.require(:id))
|
85
|
+
end
|
86
|
+
|
87
|
+
def contact_params
|
88
|
+
params.require(:contact).permit(:name, :age, :email)
|
89
|
+
end
|
90
|
+
# def contact_params
|
91
|
+
# params.require(:contact).permit!
|
92
|
+
# end
|
93
|
+
|
94
|
+
def all_contacts
|
95
|
+
@contacts = Contact.all
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<%= turbo_stream.update("flash", partial: "shared/flash") %>
|
2
|
+
<%= turbo_stream.append("contacts-list", partial: "contacts/contact", locals: { contact: @contact }) %>
|
3
|
+
<%= turbo_stream.update("contacts-count", partial: "contacts/count", locals: { contacts: @contacts }) %>
|
4
|
+
<%= turbo_stream.update("contact-form", partial: "contacts/form", locals: { contact: Contact.new }) %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<div class="prose lg:prose-xl">
|
2
|
+
<h1>Edit contact</h1>
|
3
|
+
</div>
|
4
|
+
|
5
|
+
<div class="grid grid-cols-2 gap-4 mt-8">
|
6
|
+
<div class="bg-gray-100 p-8">
|
7
|
+
<%= render partial: "list", locals: { contacts: @contacts } %>
|
8
|
+
</div>
|
9
|
+
<div class="form-control w-full max-w-xs">
|
10
|
+
<%= render partial: "form", locals: { contact: @contact } %>
|
11
|
+
</div>
|
12
|
+
</div>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<div class="prose lg:prose-xl">
|
2
|
+
<h1>New contact</h1>
|
3
|
+
</div>
|
4
|
+
|
5
|
+
<div class="grid grid-cols-2 gap-4 mt-8">
|
6
|
+
<div class="bg-gray-100 p-8">
|
7
|
+
<%= render partial: "list", locals: { contacts: @contacts } %>
|
8
|
+
</div>
|
9
|
+
<div class="form-control w-full max-w-xs" id="contact-form">
|
10
|
+
<%= render partial: "form", locals: { contact: @contact } %>
|
11
|
+
</div>
|
12
|
+
</div>
|