basecoat 0.1.1
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 +7 -0
- data/.idea/.gitignore +8 -0
- data/.idea/basecoat.iml +17 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +194 -0
- data/Rakefile +4 -0
- data/lib/basecoat/railtie.rb +11 -0
- data/lib/basecoat/version.rb +5 -0
- data/lib/basecoat.rb +8 -0
- data/lib/generators/basecoat/templates/application.html.erb +16 -0
- data/lib/generators/basecoat/templates/devise/confirmations/new.html.erb +27 -0
- data/lib/generators/basecoat/templates/devise/mailer/confirmation_instructions.html.erb +5 -0
- data/lib/generators/basecoat/templates/devise/mailer/email_changed.html.erb +7 -0
- data/lib/generators/basecoat/templates/devise/mailer/password_change.html.erb +3 -0
- data/lib/generators/basecoat/templates/devise/mailer/reset_password_instructions.html.erb +8 -0
- data/lib/generators/basecoat/templates/devise/mailer/unlock_instructions.html.erb +7 -0
- data/lib/generators/basecoat/templates/devise/passwords/edit.html.erb +40 -0
- data/lib/generators/basecoat/templates/devise/passwords/new.html.erb +31 -0
- data/lib/generators/basecoat/templates/devise/registrations/edit.html.erb +63 -0
- data/lib/generators/basecoat/templates/devise/registrations/new.html.erb +40 -0
- data/lib/generators/basecoat/templates/devise/sessions/new.html.erb +38 -0
- data/lib/generators/basecoat/templates/devise/shared/_error_messages.html.erb +15 -0
- data/lib/generators/basecoat/templates/devise/shared/_links.html.erb +27 -0
- data/lib/generators/basecoat/templates/devise/unlocks/new.html.erb +29 -0
- data/lib/generators/basecoat/templates/devise.html.erb +36 -0
- data/lib/generators/basecoat/templates/layouts/_alert.html.erb +6 -0
- data/lib/generators/basecoat/templates/layouts/_aside.html.erb +21 -0
- data/lib/generators/basecoat/templates/layouts/_form_errors.html.erb +13 -0
- data/lib/generators/basecoat/templates/layouts/_head.html.erb +21 -0
- data/lib/generators/basecoat/templates/layouts/_header.html.erb +12 -0
- data/lib/generators/basecoat/templates/layouts/_notice.html.erb +18 -0
- data/lib/generators/basecoat/templates/pagy.scss +31 -0
- data/lib/generators/basecoat/templates/passwords/edit.html.erb +30 -0
- data/lib/generators/basecoat/templates/passwords/new.html.erb +25 -0
- data/lib/generators/basecoat/templates/scaffold_hook.rb +36 -0
- data/lib/generators/basecoat/templates/sessions/new.html.erb +30 -0
- data/lib/generators/basecoat/templates/sessions.html.erb +36 -0
- data/lib/tasks/basecoat.rake +281 -0
- data/lib/templates/erb/scaffold/_form.html.erb.tt +43 -0
- data/lib/templates/erb/scaffold/edit.html.erb.tt +21 -0
- data/lib/templates/erb/scaffold/index.html.erb.tt +35 -0
- data/lib/templates/erb/scaffold/new.html.erb.tt +20 -0
- data/lib/templates/erb/scaffold/partial.html.erb.tt +20 -0
- data/lib/templates/erb/scaffold/show.html.erb.tt +23 -0
- data/sig/basecoat.rbs +4 -0
- metadata +104 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
namespace :basecoat do
|
|
4
|
+
desc "Install Basecoat application layout and partials"
|
|
5
|
+
task :install do
|
|
6
|
+
# Install basecoat-css (always install via yarn/npm for CSS)
|
|
7
|
+
puts "\n📦 Installing basecoat-css..."
|
|
8
|
+
system("yarn add basecoat-css") || system("npm install basecoat-css")
|
|
9
|
+
puts " Installed: basecoat-css via yarn/npm"
|
|
10
|
+
|
|
11
|
+
# If using importmap, also add to importmap.rb for JS
|
|
12
|
+
if File.exist?(Rails.root.join("config/importmap.rb"))
|
|
13
|
+
importmap_path = Rails.root.join("config/importmap.rb")
|
|
14
|
+
importmap_content = File.read(importmap_path)
|
|
15
|
+
unless importmap_content.include?("basecoat-css")
|
|
16
|
+
File.open(importmap_path, "a") do |f|
|
|
17
|
+
f.puts "\npin \"basecoat-css/all\", to: \"https://cdn.jsdelivr.net/npm/basecoat-css@0.3.2/dist/js/all.js\""
|
|
18
|
+
end
|
|
19
|
+
puts " Added: basecoat-css to config/importmap.rb"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Add JavaScript imports and code
|
|
24
|
+
js_path = Rails.root.join("app/javascript/application.js")
|
|
25
|
+
if File.exist?(js_path)
|
|
26
|
+
js_content = File.read(js_path)
|
|
27
|
+
|
|
28
|
+
unless js_content.include?("basecoat-css")
|
|
29
|
+
# Add import after the last import line
|
|
30
|
+
js_content = js_content.sub(/(import\s+.*\n)(?!import)/, "\\1import \"basecoat-css/all\"\n")
|
|
31
|
+
File.write(js_path, js_content)
|
|
32
|
+
puts " Added: basecoat-css import to app/javascript/application.js"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Add view transitions code
|
|
36
|
+
unless js_content.include?("turbo:before-frame-render")
|
|
37
|
+
view_transition_code = <<~JS
|
|
38
|
+
|
|
39
|
+
// View transitions for turbo frame navigation
|
|
40
|
+
addEventListener("turbo:before-frame-render", (event) => {
|
|
41
|
+
if (document.startViewTransition) {
|
|
42
|
+
const originalRender = event.detail.render
|
|
43
|
+
event.detail.render = async (currentElement, newElement) => {
|
|
44
|
+
const transition = document.startViewTransition(() => originalRender(currentElement, newElement))
|
|
45
|
+
await transition.finished
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
JS
|
|
50
|
+
File.open(js_path, "a") { |f| f.write(view_transition_code) }
|
|
51
|
+
puts " Added: View transitions to app/javascript/application.js"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Add dark mode toggle code
|
|
55
|
+
unless js_content.include?("basecoat:theme")
|
|
56
|
+
dark_mode_code = <<~JS
|
|
57
|
+
|
|
58
|
+
// Dark mode toggle
|
|
59
|
+
const apply = dark => {
|
|
60
|
+
document.documentElement.classList.toggle('dark', dark);
|
|
61
|
+
try { localStorage.setItem('themeMode', dark ? 'dark' : 'light'); } catch (_) {}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Apply theme on initial load (runs immediately to prevent flash)
|
|
65
|
+
try {
|
|
66
|
+
const stored = localStorage.getItem('themeMode');
|
|
67
|
+
if (stored ? stored === 'dark'
|
|
68
|
+
: matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
69
|
+
document.documentElement.classList.add('dark');
|
|
70
|
+
}
|
|
71
|
+
} catch (_) {}
|
|
72
|
+
|
|
73
|
+
// Set up theme toggle event listener
|
|
74
|
+
document.addEventListener('basecoat:theme', (event) => {
|
|
75
|
+
const mode = event.detail?.mode;
|
|
76
|
+
apply(mode === 'dark' ? true
|
|
77
|
+
: mode === 'light' ? false
|
|
78
|
+
: !document.documentElement.classList.contains('dark'));
|
|
79
|
+
})
|
|
80
|
+
JS
|
|
81
|
+
File.open(js_path, "a") { |f| f.write(dark_mode_code) }
|
|
82
|
+
puts " Added: Dark mode toggle to app/javascript/application.js"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Add CSS imports and styles
|
|
87
|
+
# Check for Tailwind v4 setup first
|
|
88
|
+
if File.exist?(Rails.root.join("app/assets/tailwind/application.css"))
|
|
89
|
+
tailwind_css = Rails.root.join("app/assets/tailwind/application.css")
|
|
90
|
+
content = File.read(tailwind_css)
|
|
91
|
+
|
|
92
|
+
# Add basecoat-css import if not present
|
|
93
|
+
unless content.include?("basecoat-css")
|
|
94
|
+
# Add after tailwindcss import
|
|
95
|
+
updated_content = content.sub(/(@import "tailwindcss";)/, "\\1\n@import \"basecoat-css\";")
|
|
96
|
+
File.write(tailwind_css, updated_content)
|
|
97
|
+
puts " Added: basecoat-css import to app/assets/tailwind/application.css"
|
|
98
|
+
end
|
|
99
|
+
else
|
|
100
|
+
# Traditional setup with app/assets/stylesheets
|
|
101
|
+
css_path = Rails.root.join("app/assets/stylesheets/application.css")
|
|
102
|
+
if File.exist?(css_path)
|
|
103
|
+
css_content = File.read(css_path)
|
|
104
|
+
|
|
105
|
+
unless css_content.include?("view-transition")
|
|
106
|
+
css_code = <<~CSS
|
|
107
|
+
.field_with_errors label {
|
|
108
|
+
color: var(--color-destructive);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.field_with_errors input {
|
|
112
|
+
border-color: var(--color-destructive);
|
|
113
|
+
}
|
|
114
|
+
CSS
|
|
115
|
+
File.open(css_path, "a") { |f| f.write(css_code) }
|
|
116
|
+
puts " Added: View transition styles to app/assets/stylesheets/application.css"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Copy application layout
|
|
122
|
+
layout_source = File.expand_path("../generators/basecoat/templates/application.html.erb", __dir__)
|
|
123
|
+
layout_destination = Rails.root.join("app/views/layouts/application.html.erb")
|
|
124
|
+
|
|
125
|
+
FileUtils.mkdir_p(File.dirname(layout_destination))
|
|
126
|
+
FileUtils.cp(layout_source, layout_destination)
|
|
127
|
+
puts " Created: app/views/layouts/application.html.erb"
|
|
128
|
+
|
|
129
|
+
# Copy layout partials
|
|
130
|
+
partials_source = File.expand_path("../generators/basecoat/templates/layouts", __dir__)
|
|
131
|
+
partials_destination = Rails.root.join("app/views/layouts")
|
|
132
|
+
|
|
133
|
+
Dir.glob("#{partials_source}/*").each do |file|
|
|
134
|
+
filename = File.basename(file)
|
|
135
|
+
FileUtils.cp(file, partials_destination.join(filename))
|
|
136
|
+
puts " Created: app/views/layouts/#{filename}"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Copy scaffold hook initializer
|
|
140
|
+
initializer_source = File.expand_path("../generators/basecoat/templates/scaffold_hook.rb", __dir__)
|
|
141
|
+
initializer_destination = Rails.root.join("config/initializers/scaffold_hook.rb")
|
|
142
|
+
|
|
143
|
+
FileUtils.mkdir_p(File.dirname(initializer_destination))
|
|
144
|
+
FileUtils.cp(initializer_source, initializer_destination)
|
|
145
|
+
puts " Created: config/initializers/scaffold_hook.rb"
|
|
146
|
+
|
|
147
|
+
puts "\n✓ Basecoat installed successfully!"
|
|
148
|
+
puts " Scaffold templates are automatically available from the gem."
|
|
149
|
+
puts " You can now run: rails generate scaffold YourModel"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
namespace :install do
|
|
153
|
+
desc "Install Basecoat Devise views and layout"
|
|
154
|
+
task :devise do
|
|
155
|
+
# Copy devise views
|
|
156
|
+
devise_source = File.expand_path("../generators/basecoat/templates/devise", __dir__)
|
|
157
|
+
devise_destination = Rails.root.join("app/views/devise")
|
|
158
|
+
|
|
159
|
+
FileUtils.mkdir_p(devise_destination)
|
|
160
|
+
FileUtils.cp_r("#{devise_source}/.", devise_destination)
|
|
161
|
+
puts " Created: app/views/devise/"
|
|
162
|
+
|
|
163
|
+
# Copy devise layout
|
|
164
|
+
layout_source = File.expand_path("../generators/basecoat/templates/devise.html.erb", __dir__)
|
|
165
|
+
layout_destination = Rails.root.join("app/views/layouts/devise.html.erb")
|
|
166
|
+
|
|
167
|
+
FileUtils.mkdir_p(File.dirname(layout_destination))
|
|
168
|
+
FileUtils.cp(layout_source, layout_destination)
|
|
169
|
+
puts " Created: app/views/layouts/devise.html.erb"
|
|
170
|
+
|
|
171
|
+
# Add user dropdown to header partial
|
|
172
|
+
header_path = Rails.root.join("app/views/layouts/_header.html.erb")
|
|
173
|
+
if File.exist?(header_path)
|
|
174
|
+
header_content = File.read(header_path)
|
|
175
|
+
unless header_content.include?("dropdown-user")
|
|
176
|
+
user_dropdown = <<~HTML
|
|
177
|
+
|
|
178
|
+
<% if defined?(user_signed_in?) && user_signed_in? %>
|
|
179
|
+
<div id="dropdown-user" class="dropdown-menu">
|
|
180
|
+
<button type="button" id="dropdown-user-trigger" aria-haspopup="menu" aria-controls="dropdown-user-menu" aria-expanded="false" class="btn-icon-ghost rounded-full size-8">
|
|
181
|
+
<img alt="<%= current_user.email %>" src="https://github.com/lafeber.png" class="size-8 shrink-0 rounded-full">
|
|
182
|
+
</button>
|
|
183
|
+
<div id="dropdown-user-popover" data-popover="" aria-hidden="true" data-align="end">
|
|
184
|
+
<div role="menu" id="dropdown-user-menu" aria-labelledby="dropdown-user-trigger">
|
|
185
|
+
<div class="px-1 py-1.5">
|
|
186
|
+
<%= button_to destroy_user_session_path, method: :delete, class: "btn-link" do %>
|
|
187
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>
|
|
188
|
+
Log out
|
|
189
|
+
<% end %>
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
<% end %>
|
|
195
|
+
HTML
|
|
196
|
+
updated_content = header_content.sub("<!-- DEVISE_USER_DROPDOWN -->", user_dropdown)
|
|
197
|
+
File.write(header_path, updated_content)
|
|
198
|
+
puts " Added: User dropdown to app/views/layouts/_header.html.erb"
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
puts "\n✓ Basecoat Devise views installed successfully!"
|
|
203
|
+
puts " Make sure you have Devise configured in your application."
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
desc "Install Basecoat Pagy pagination styles"
|
|
207
|
+
task :pagy do
|
|
208
|
+
pagy_source = File.expand_path("../generators/basecoat/templates/pagy.scss", __dir__)
|
|
209
|
+
|
|
210
|
+
# Check if using Tailwind v4 setup (app/assets/tailwind)
|
|
211
|
+
if File.exist?(Rails.root.join("app/assets/tailwind/application.css"))
|
|
212
|
+
# Copy pagy styles to tailwind directory
|
|
213
|
+
pagy_destination = Rails.root.join("app/assets/tailwind/pagy.scss")
|
|
214
|
+
FileUtils.mkdir_p(File.dirname(pagy_destination))
|
|
215
|
+
FileUtils.cp(pagy_source, pagy_destination)
|
|
216
|
+
puts " Created: app/assets/tailwind/pagy.scss"
|
|
217
|
+
|
|
218
|
+
# Add import to tailwind application.css
|
|
219
|
+
tailwind_css = Rails.root.join("app/assets/tailwind/application.css")
|
|
220
|
+
content = File.read(tailwind_css)
|
|
221
|
+
unless content.include?("pagy")
|
|
222
|
+
File.open(tailwind_css, "a") do |f|
|
|
223
|
+
f.puts '@import "./pagy.scss";'
|
|
224
|
+
end
|
|
225
|
+
puts " Added import to: app/assets/tailwind/application.css"
|
|
226
|
+
end
|
|
227
|
+
else
|
|
228
|
+
# Copy pagy styles to stylesheets directory
|
|
229
|
+
pagy_destination = Rails.root.join("app/assets/stylesheets/pagy.scss")
|
|
230
|
+
FileUtils.mkdir_p(File.dirname(pagy_destination))
|
|
231
|
+
FileUtils.cp(pagy_source, pagy_destination)
|
|
232
|
+
puts " Created: app/assets/stylesheets/pagy.scss"
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
puts "\n✓ Basecoat Pagy styles installed successfully!"
|
|
236
|
+
puts " Make sure you have Pagy configured in your application."
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
desc "Install Basecoat authentication views and layout"
|
|
240
|
+
task :authentication do
|
|
241
|
+
# Copy sessions views
|
|
242
|
+
sessions_source = File.expand_path("../generators/basecoat/templates/sessions", __dir__)
|
|
243
|
+
sessions_destination = Rails.root.join("app/views/sessions")
|
|
244
|
+
|
|
245
|
+
FileUtils.mkdir_p(sessions_destination)
|
|
246
|
+
FileUtils.cp_r("#{sessions_source}/.", sessions_destination)
|
|
247
|
+
puts " Created: app/views/sessions/"
|
|
248
|
+
|
|
249
|
+
# Copy passwords views
|
|
250
|
+
passwords_source = File.expand_path("../generators/basecoat/templates/passwords", __dir__)
|
|
251
|
+
passwords_destination = Rails.root.join("app/views/passwords")
|
|
252
|
+
|
|
253
|
+
FileUtils.mkdir_p(passwords_destination)
|
|
254
|
+
FileUtils.cp_r("#{passwords_source}/.", passwords_destination)
|
|
255
|
+
puts " Created: app/views/passwords/"
|
|
256
|
+
|
|
257
|
+
# Copy sessions layout
|
|
258
|
+
layout_source = File.expand_path("../generators/basecoat/templates/sessions.html.erb", __dir__)
|
|
259
|
+
layout_destination = Rails.root.join("app/views/layouts/sessions.html.erb")
|
|
260
|
+
|
|
261
|
+
FileUtils.mkdir_p(File.dirname(layout_destination))
|
|
262
|
+
FileUtils.cp(layout_source, layout_destination)
|
|
263
|
+
puts " Created: app/views/layouts/sessions.html.erb"
|
|
264
|
+
|
|
265
|
+
# Add layout to passwords_controller
|
|
266
|
+
passwords_controller = Rails.root.join("app/controllers/passwords_controller.rb")
|
|
267
|
+
if File.exist?(passwords_controller)
|
|
268
|
+
content = File.read(passwords_controller)
|
|
269
|
+
unless content.include?('layout "sessions"')
|
|
270
|
+
# Add after the class declaration
|
|
271
|
+
updated_content = content.sub(/(class PasswordsController < ApplicationController\n)/, "\\1 layout \"sessions\"\n\n")
|
|
272
|
+
File.write(passwords_controller, updated_content)
|
|
273
|
+
puts " Added layout to: app/controllers/passwords_controller.rb"
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
puts "\n✓ Basecoat authentication views installed successfully!"
|
|
278
|
+
puts " Make sure you have Rails authentication configured in your application."
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<%%= form_with(model: <%= model_resource_name %>, class: "space-y-6") do |form| %>
|
|
2
|
+
<%%= render "/layouts/form_errors", object: <%= singular_table_name %> if <%= singular_table_name %>.errors.any? %>
|
|
3
|
+
|
|
4
|
+
<% attributes.each do |attribute| -%>
|
|
5
|
+
<% required = attribute.to_s.include?('{null}') -%>
|
|
6
|
+
<div class="grid gap-3">
|
|
7
|
+
<% if attribute.password_digest? -%>
|
|
8
|
+
<%%= form.label :password, class: "label" %>
|
|
9
|
+
<%%= form.password_field :password, class: "input", required: true %>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div class="grid gap-3">
|
|
13
|
+
<%%= form.label :password_confirmation, class: "label" %>
|
|
14
|
+
<%%= form.password_field :password_confirmation, class: "input", required: true %>
|
|
15
|
+
<% elsif attribute.attachments? -%>
|
|
16
|
+
<%%= form.label :<%= attribute.column_name %>, class: "label" %>
|
|
17
|
+
<%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true, class: "input"<%= ", required: true" if required %> %>
|
|
18
|
+
<% elsif attribute.field_type == :textarea -%>
|
|
19
|
+
<%%= form.label :<%= attribute.column_name %>, class: "label" %>
|
|
20
|
+
<%%= form.text_area :<%= attribute.column_name %>, class: "textarea", rows: 4<%= ", required: true" if required %> %>
|
|
21
|
+
<% elsif attribute.field_type == :checkbox -%>
|
|
22
|
+
<%%= form.label :<%= attribute.column_name %>, class: "label" do %>
|
|
23
|
+
<%%= form.check_box :<%= attribute.column_name %>, class: "input", role: "switch" %>
|
|
24
|
+
<%= attribute.human_name %>
|
|
25
|
+
<%% end %>
|
|
26
|
+
<% elsif attribute.field_type == :datetime_local_field || attribute.field_type == :date_field || attribute.field_type == :time_field -%>
|
|
27
|
+
<%%= form.label :<%= attribute.column_name %>, class: "label" %>
|
|
28
|
+
<%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "input"<%= ", required: true" if required %> %>
|
|
29
|
+
<% elsif attribute.field_type == :number_field -%>
|
|
30
|
+
<%%= form.label :<%= attribute.column_name %>, class: "label" %>
|
|
31
|
+
<%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "input"<%= ", required: true" if required %> %>
|
|
32
|
+
<% else -%>
|
|
33
|
+
<%%= form.label :<%= attribute.column_name %>, class: "label" %>
|
|
34
|
+
<%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "input"<%= ", required: true" if required %> %>
|
|
35
|
+
<% end -%>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<% end -%>
|
|
39
|
+
<div class="flex justify-end space-x-3 pt-6">
|
|
40
|
+
<%%= link_to "Cancel", <%= index_helper(type: :path) %>, class: "btn-outline" %>
|
|
41
|
+
<%%= form.submit class: "btn" %>
|
|
42
|
+
</div>
|
|
43
|
+
<%% end %>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%%= turbo_frame_tag "main_content" do %>
|
|
2
|
+
<%%= render 'layouts/notice', notice: notice if notice %>
|
|
3
|
+
<div class="container mx-auto px-4 py-8">
|
|
4
|
+
<div class="max-w-2xl mx-auto">
|
|
5
|
+
<div class="card">
|
|
6
|
+
<header>
|
|
7
|
+
<h2>Editing <%= human_name.downcase %></h2>
|
|
8
|
+
<p>Update the form below to modify this <%= human_name.downcase %>.</p>
|
|
9
|
+
</header>
|
|
10
|
+
<section>
|
|
11
|
+
<%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
|
|
12
|
+
</section>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div class="flex flex-wrap gap-3 mt-6">
|
|
16
|
+
<%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, class: "btn-outline", data: { turbo_action: "advance" } %>
|
|
17
|
+
<%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "btn-outline", data: { turbo_action: "advance" } %>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<%% end %>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<%%= turbo_frame_tag "main_content" do %>
|
|
2
|
+
<%%= render 'layouts/notice', notice: notice if notice %>
|
|
3
|
+
<div class="container mx-auto px-4 py-8">
|
|
4
|
+
<div class="flex justify-between items-center mb-8">
|
|
5
|
+
<h1 class="text-3xl"><%= human_name.pluralize %></h1>
|
|
6
|
+
<%%= link_to "New <%= human_name.downcase %>", <%= new_helper(type: :path) %>, class: "btn", data: { turbo_action: "advance" } %>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div class="grid gap-4" id="<%= plural_table_name %>">
|
|
10
|
+
<%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
|
|
11
|
+
<div class="card">
|
|
12
|
+
<section>
|
|
13
|
+
<%%= render <%= singular_table_name %> %>
|
|
14
|
+
</section>
|
|
15
|
+
<footer class="flex items-center">
|
|
16
|
+
<%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(singular_table_name) %>, class: "btn-outline", data: { turbo_action: "advance" } %>
|
|
17
|
+
</footer>
|
|
18
|
+
</div>
|
|
19
|
+
<%% end %>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<%% if @<%= plural_table_name %>.empty? %>
|
|
23
|
+
<div class="text-center py-12">
|
|
24
|
+
<div class="mb-4">
|
|
25
|
+
<svg class="mx-auto h-12 w-12" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
26
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2M4 13h2m13-8V4a1 1 0 00-1-1H7a1 1 0 00-1 1v1h10z" />
|
|
27
|
+
</svg>
|
|
28
|
+
</div>
|
|
29
|
+
<h3 class="text-lg font-medium mb-2">No <%= human_name.pluralize.downcase %> yet</h3>
|
|
30
|
+
<p class="mb-6">Get started by creating your first <%= human_name.downcase %>.</p>
|
|
31
|
+
<%%= link_to "New <%= human_name.downcase %>", <%= new_helper(type: :path) %>, class: "btn", data: { turbo_action: "advance" } %>
|
|
32
|
+
</div>
|
|
33
|
+
<%% end %>
|
|
34
|
+
</div>
|
|
35
|
+
<%% end %>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<%%= turbo_frame_tag "main_content" do %>
|
|
2
|
+
<%%= render 'layouts/notice', notice: notice if notice %>
|
|
3
|
+
<div class="container mx-auto px-4 py-8">
|
|
4
|
+
<div class="max-w-2xl mx-auto">
|
|
5
|
+
<div class="card">
|
|
6
|
+
<header>
|
|
7
|
+
<h2>New <%= human_name.downcase %></h2>
|
|
8
|
+
<p>Fill in the form below to create a new <%= human_name.downcase %>.</p>
|
|
9
|
+
</header>
|
|
10
|
+
<section>
|
|
11
|
+
<%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
|
|
12
|
+
</section>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div class="mt-6">
|
|
16
|
+
<%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "btn-outline", data: { turbo_action: "advance" } %>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
<%% end %>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<div id="<%%= dom_id <%= singular_table_name %> %>" class="space-y-4">
|
|
2
|
+
<% attributes.reject(&:password_digest?).each do |attribute| -%>
|
|
3
|
+
<div class="flex flex-col sm:flex-row sm:items-center py-2">
|
|
4
|
+
<dt class="text-sm font-medium sm:w-1/3 mb-1 sm:mb-0">
|
|
5
|
+
<%= attribute.human_name %>:
|
|
6
|
+
</dt>
|
|
7
|
+
<dd class="text-sm sm:w-2/3">
|
|
8
|
+
<% if attribute.attachment? -%>
|
|
9
|
+
<%%= link_to <%= singular_table_name %>.<%= attribute.column_name %>.filename, <%= singular_table_name %>.<%= attribute.column_name %>, target: :_blank, class: "text-blue-600 hover:text-blue-800 underline" if <%= singular_table_name %>.<%= attribute.column_name %>.attached? %>
|
|
10
|
+
<% elsif attribute.attachments? -%>
|
|
11
|
+
<%% <%= singular_table_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %>
|
|
12
|
+
<div><%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %>, target: :_blank, class: "text-blue-600 hover:text-blue-800 underline" %></div>
|
|
13
|
+
<%% end %>
|
|
14
|
+
<% else -%>
|
|
15
|
+
<%%= <%= singular_table_name %>.<%= attribute.column_name %> %>
|
|
16
|
+
<% end -%>
|
|
17
|
+
</dd>
|
|
18
|
+
</div>
|
|
19
|
+
<% end -%>
|
|
20
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<%%= turbo_frame_tag "main_content" do %>
|
|
2
|
+
<%%= render 'layouts/notice', notice: notice if notice %>
|
|
3
|
+
<div class="container mx-auto px-4 py-8">
|
|
4
|
+
<div class="max-w-2xl mx-auto">
|
|
5
|
+
<div class="card">
|
|
6
|
+
<section>
|
|
7
|
+
<%%= render @<%= singular_table_name %> %>
|
|
8
|
+
</section>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<div class="flex flex-wrap gap-3 mt-6">
|
|
12
|
+
<%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %>, class: "btn", data: { turbo_action: "advance" } %>
|
|
13
|
+
<%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "btn-outline", data: { turbo_action: "advance" } %>
|
|
14
|
+
<%%= button_to "Delete this <%= human_name.downcase %>",
|
|
15
|
+
<%= model_resource_name(prefix: "@") %>,
|
|
16
|
+
method: :delete,
|
|
17
|
+
class: "btn-destructive",
|
|
18
|
+
data: { turbo_confirm: "Are you sure you want to delete this <%= human_name.downcase %>?", turbo_action: "advance" },
|
|
19
|
+
form_class: "inline-block" %>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
<%% end %>
|
data/sig/basecoat.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: basecoat
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Martijn Lafeber
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: tailwindcss-rails
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '4.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '4.0'
|
|
26
|
+
description: Provides beautiful, production-ready scaffold templates and Devise views
|
|
27
|
+
styled with Basecoat CSS framework
|
|
28
|
+
email:
|
|
29
|
+
- lafeber@gmail.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- ".idea/.gitignore"
|
|
35
|
+
- ".idea/basecoat.iml"
|
|
36
|
+
- ".idea/misc.xml"
|
|
37
|
+
- ".idea/modules.xml"
|
|
38
|
+
- ".idea/vcs.xml"
|
|
39
|
+
- LICENSE.txt
|
|
40
|
+
- README.md
|
|
41
|
+
- Rakefile
|
|
42
|
+
- lib/basecoat.rb
|
|
43
|
+
- lib/basecoat/railtie.rb
|
|
44
|
+
- lib/basecoat/version.rb
|
|
45
|
+
- lib/generators/basecoat/templates/application.html.erb
|
|
46
|
+
- lib/generators/basecoat/templates/devise.html.erb
|
|
47
|
+
- lib/generators/basecoat/templates/devise/confirmations/new.html.erb
|
|
48
|
+
- lib/generators/basecoat/templates/devise/mailer/confirmation_instructions.html.erb
|
|
49
|
+
- lib/generators/basecoat/templates/devise/mailer/email_changed.html.erb
|
|
50
|
+
- lib/generators/basecoat/templates/devise/mailer/password_change.html.erb
|
|
51
|
+
- lib/generators/basecoat/templates/devise/mailer/reset_password_instructions.html.erb
|
|
52
|
+
- lib/generators/basecoat/templates/devise/mailer/unlock_instructions.html.erb
|
|
53
|
+
- lib/generators/basecoat/templates/devise/passwords/edit.html.erb
|
|
54
|
+
- lib/generators/basecoat/templates/devise/passwords/new.html.erb
|
|
55
|
+
- lib/generators/basecoat/templates/devise/registrations/edit.html.erb
|
|
56
|
+
- lib/generators/basecoat/templates/devise/registrations/new.html.erb
|
|
57
|
+
- lib/generators/basecoat/templates/devise/sessions/new.html.erb
|
|
58
|
+
- lib/generators/basecoat/templates/devise/shared/_error_messages.html.erb
|
|
59
|
+
- lib/generators/basecoat/templates/devise/shared/_links.html.erb
|
|
60
|
+
- lib/generators/basecoat/templates/devise/unlocks/new.html.erb
|
|
61
|
+
- lib/generators/basecoat/templates/layouts/_alert.html.erb
|
|
62
|
+
- lib/generators/basecoat/templates/layouts/_aside.html.erb
|
|
63
|
+
- lib/generators/basecoat/templates/layouts/_form_errors.html.erb
|
|
64
|
+
- lib/generators/basecoat/templates/layouts/_head.html.erb
|
|
65
|
+
- lib/generators/basecoat/templates/layouts/_header.html.erb
|
|
66
|
+
- lib/generators/basecoat/templates/layouts/_notice.html.erb
|
|
67
|
+
- lib/generators/basecoat/templates/pagy.scss
|
|
68
|
+
- lib/generators/basecoat/templates/passwords/edit.html.erb
|
|
69
|
+
- lib/generators/basecoat/templates/passwords/new.html.erb
|
|
70
|
+
- lib/generators/basecoat/templates/scaffold_hook.rb
|
|
71
|
+
- lib/generators/basecoat/templates/sessions.html.erb
|
|
72
|
+
- lib/generators/basecoat/templates/sessions/new.html.erb
|
|
73
|
+
- lib/tasks/basecoat.rake
|
|
74
|
+
- lib/templates/erb/scaffold/_form.html.erb.tt
|
|
75
|
+
- lib/templates/erb/scaffold/edit.html.erb.tt
|
|
76
|
+
- lib/templates/erb/scaffold/index.html.erb.tt
|
|
77
|
+
- lib/templates/erb/scaffold/new.html.erb.tt
|
|
78
|
+
- lib/templates/erb/scaffold/partial.html.erb.tt
|
|
79
|
+
- lib/templates/erb/scaffold/show.html.erb.tt
|
|
80
|
+
- sig/basecoat.rbs
|
|
81
|
+
homepage: https://github.com/lafeber/basecoat-rb
|
|
82
|
+
licenses:
|
|
83
|
+
- MIT
|
|
84
|
+
metadata:
|
|
85
|
+
homepage_uri: https://github.com/lafeber/basecoat-rb
|
|
86
|
+
source_code_uri: https://github.com/lafeber/basecoat-rb
|
|
87
|
+
rdoc_options: []
|
|
88
|
+
require_paths:
|
|
89
|
+
- lib
|
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - ">="
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: 3.2.0
|
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '0'
|
|
100
|
+
requirements: []
|
|
101
|
+
rubygems_version: 3.6.7
|
|
102
|
+
specification_version: 4
|
|
103
|
+
summary: Rails scaffold templates and Devise views styled with Basecoat CSS
|
|
104
|
+
test_files: []
|