kaze 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/kaze/commands/install_command.rb +25 -13
- data/lib/kaze/commands/installs_hotwire_stack.rb +11 -8
- data/lib/kaze/commands/installs_inertia_stacks.rb +34 -24
- data/lib/kaze/commands/version_command.rb +6 -0
- data/lib/kaze/version.rb +1 -1
- data/lib/kaze.rb +1 -3
- data/stubs/default/app/forms/auth/login_form.rb +2 -8
- data/stubs/default/app/forms/auth/new_password_form.rb +1 -1
- data/stubs/default/app/forms/update_profile_information_form.rb +1 -1
- data/stubs/default/app/mailers/application_mailer.rb +4 -4
- data/stubs/default/app/mailers/user_mailer.rb +1 -1
- data/stubs/default/app/models/auth.rb +57 -0
- data/stubs/default/app/models/current.rb +1 -1
- data/stubs/default/app/validators/current_password_validator.rb +1 -1
- data/stubs/default/app/validators/email_validator.rb +1 -1
- data/stubs/default/app/validators/lowercase_validator.rb +2 -2
- data/stubs/default/app/views/layouts/mailer.html.erb +367 -372
- data/stubs/default/app/views/layouts/mailer.text.erb +1 -4
- data/stubs/default/app/views/user_mailer/reset_password.html.erb +21 -26
- data/stubs/default/config/routes.rb +16 -16
- data/stubs/default/db/migrate/20240101000001_create_delayed_jobs.rb +1 -1
- data/stubs/default/test/factories/users.rb +7 -0
- data/stubs/default/test/integration/auth/authentication_test.rb +43 -0
- data/stubs/default/test/integration/auth/password_reset_test.rb +41 -0
- data/stubs/default/test/integration/auth/registration_test.rb +21 -0
- data/stubs/default/test/integration/password_update_test.rb +28 -0
- data/stubs/default/test/integration/profile_test.rb +51 -0
- data/stubs/default/test/test_helper.rb +38 -0
- data/stubs/hotwire/app/components/danger_button_component.rb +1 -1
- data/stubs/hotwire/app/components/dropdown_component.html.erb +17 -18
- data/stubs/hotwire/app/components/dropdown_component.rb +7 -7
- data/stubs/hotwire/app/components/modal_component.html.erb +55 -59
- data/stubs/hotwire/app/components/modal_component.rb +6 -6
- data/stubs/hotwire/app/components/primary_button_component.rb +1 -1
- data/stubs/hotwire/app/components/secondary_button_component.rb +1 -1
- data/stubs/hotwire/app/controllers/application_controller.rb +1 -0
- data/stubs/hotwire/app/controllers/auth/authenticated_session_controller.rb +12 -9
- data/stubs/hotwire/app/controllers/auth/new_password_controller.rb +7 -5
- data/stubs/hotwire/app/controllers/auth/password_reset_link_controller.rb +7 -5
- data/stubs/hotwire/app/controllers/auth/registered_user_controller.rb +7 -5
- data/stubs/hotwire/app/controllers/concerns/authenticate.rb +5 -20
- data/stubs/hotwire/app/controllers/concerns/redirect_if_authenticated.rb +19 -0
- data/stubs/hotwire/app/controllers/concerns/set_current_auth.rb +9 -0
- data/stubs/hotwire/app/controllers/password_controller.rb +3 -3
- data/stubs/hotwire/app/controllers/profile_controller.rb +11 -9
- data/stubs/hotwire/app/controllers/welcome_controller.rb +1 -1
- data/stubs/hotwire/app/javascript/application.js +3 -3
- data/stubs/hotwire/app/views/auth/forgot_password.html.erb +12 -17
- data/stubs/hotwire/app/views/auth/login.html.erb +0 -9
- data/stubs/hotwire/app/views/auth/register.html.erb +0 -13
- data/stubs/hotwire/app/views/auth/reset_password.html.erb +0 -7
- data/stubs/hotwire/app/views/dashboard/index.html.erb +9 -10
- data/stubs/hotwire/app/views/layouts/_navigation.html.erb +77 -87
- data/stubs/hotwire/app/views/layouts/application.html.erb +0 -9
- data/stubs/hotwire/app/views/layouts/guest.html.erb +0 -6
- data/stubs/hotwire/app/views/profile/edit.html.erb +19 -22
- data/stubs/hotwire/app/views/profile/partials/_delete_user_form.html.erb +32 -42
- data/stubs/hotwire/app/views/profile/partials/_update_password_form.html.erb +42 -55
- data/stubs/hotwire/app/views/profile/partials/_update_profile_information_form.html.erb +36 -46
- data/stubs/hotwire/app/views/welcome/index.html.erb +34 -46
- data/stubs/hotwire/config/importmap.rb +3 -3
- data/stubs/hotwire/config/tailwind.config.js +2 -2
- data/stubs/inertia-common/app/controllers/application_controller.rb +1 -0
- data/stubs/inertia-common/app/controllers/auth/authenticated_session_controller.rb +11 -8
- data/stubs/inertia-common/app/controllers/auth/new_password_controller.rb +5 -3
- data/stubs/inertia-common/app/controllers/auth/password_reset_link_controller.rb +5 -3
- data/stubs/inertia-common/app/controllers/auth/registered_user_controller.rb +5 -3
- data/stubs/inertia-common/app/controllers/concerns/authenticate.rb +5 -20
- data/stubs/inertia-common/app/controllers/concerns/handle_inertia_requests.rb +1 -1
- data/stubs/inertia-common/app/controllers/concerns/redirect_if_authenticated.rb +19 -0
- data/stubs/inertia-common/app/controllers/concerns/set_current_auth.rb +9 -0
- data/stubs/inertia-common/app/controllers/concerns/verify_csrf_token.rb +4 -4
- data/stubs/inertia-common/app/controllers/dashboard_controller.rb +1 -1
- data/stubs/inertia-common/app/controllers/password_controller.rb +1 -1
- data/stubs/inertia-common/app/controllers/profile_controller.rb +7 -5
- data/stubs/inertia-common/app/controllers/welcome_controller.rb +2 -2
- data/stubs/inertia-common/bin/vite +6 -6
- data/stubs/inertia-common/test/integration/password_update_test.rb +28 -0
- data/stubs/inertia-common/test/integration/profile_test.rb +51 -0
- data/stubs/inertia-react-ts/app/javascript/Components/ApplicationLogo.tsx +13 -9
- data/stubs/inertia-react-ts/app/javascript/Components/Checkbox.tsx +15 -12
- data/stubs/inertia-react-ts/app/javascript/Components/DangerButton.tsx +20 -15
- data/stubs/inertia-react-ts/app/javascript/Components/Dropdown.tsx +119 -87
- data/stubs/inertia-react-ts/app/javascript/Components/InputError.tsx +14 -7
- data/stubs/inertia-react-ts/app/javascript/Components/InputLabel.tsx +18 -7
- data/stubs/inertia-react-ts/app/javascript/Components/Modal.tsx +60 -60
- data/stubs/inertia-react-ts/app/javascript/Components/NavLink.tsx +21 -16
- data/stubs/inertia-react-ts/app/javascript/Components/PrimaryButton.tsx +20 -15
- data/stubs/inertia-react-ts/app/javascript/Components/ResponsiveNavLink.tsx +19 -14
- data/stubs/inertia-react-ts/app/javascript/Components/SecondaryButton.tsx +22 -16
- data/stubs/inertia-react-ts/app/javascript/Components/TextInput.tsx +35 -24
- data/stubs/inertia-react-ts/app/javascript/Layouts/AuthenticatedLayout.tsx +157 -117
- data/stubs/inertia-react-ts/app/javascript/Layouts/GuestLayout.tsx +15 -15
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ForgotPassword.tsx +52 -49
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Login.tsx +90 -82
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Register.tsx +118 -115
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ResetPassword.tsx +63 -60
- data/stubs/inertia-react-ts/app/javascript/Pages/Dashboard.tsx +23 -17
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Edit.tsx +31 -27
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.tsx +109 -99
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.tsx +121 -113
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.tsx +76 -69
- data/stubs/inertia-react-ts/app/javascript/Pages/Welcome.tsx +87 -63
- data/stubs/inertia-react-ts/app/javascript/entrypoints/application.tsx +32 -25
- data/stubs/inertia-react-ts/app/views/layouts/application.html.erb +0 -4
- data/stubs/inertia-react-ts/config/tailwind.config.js +2 -2
- data/stubs/inertia-react-ts/vite.config.ts +2 -5
- data/stubs/inertia-vue-ts/app/javascript/Components/ApplicationLogo.vue +10 -6
- data/stubs/inertia-vue-ts/app/javascript/Components/Checkbox.vue +18 -18
- data/stubs/inertia-vue-ts/app/javascript/Components/DangerButton.vue +5 -5
- data/stubs/inertia-vue-ts/app/javascript/Components/Dropdown.vue +60 -57
- data/stubs/inertia-vue-ts/app/javascript/Components/DropdownLink.vue +9 -9
- data/stubs/inertia-vue-ts/app/javascript/Components/InputError.vue +7 -7
- data/stubs/inertia-vue-ts/app/javascript/Components/InputLabel.vue +6 -6
- data/stubs/inertia-vue-ts/app/javascript/Components/Modal.vue +84 -74
- data/stubs/inertia-vue-ts/app/javascript/Components/NavLink.vue +12 -12
- data/stubs/inertia-vue-ts/app/javascript/Components/PrimaryButton.vue +5 -5
- data/stubs/inertia-vue-ts/app/javascript/Components/ResponsiveNavLink.vue +12 -12
- data/stubs/inertia-vue-ts/app/javascript/Components/SecondaryButton.vue +13 -13
- data/stubs/inertia-vue-ts/app/javascript/Components/TextInput.vue +13 -13
- data/stubs/inertia-vue-ts/app/javascript/Layouts/AuthenticatedLayout.vue +168 -136
- data/stubs/inertia-vue-ts/app/javascript/Layouts/GuestLayout.vue +15 -13
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ForgotPassword.vue +56 -49
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Login.vue +78 -72
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Register.vue +101 -97
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ResetPassword.vue +71 -68
- data/stubs/inertia-vue-ts/app/javascript/Pages/Dashboard.vue +22 -14
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Edit.vue +34 -30
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.vue +87 -83
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.vue +105 -98
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.vue +69 -59
- data/stubs/inertia-vue-ts/app/javascript/Pages/Welcome.vue +74 -47
- data/stubs/inertia-vue-ts/app/views/layouts/application.html.erb +0 -4
- data/stubs/inertia-vue-ts/config/tailwind.config.js +2 -2
- data/stubs/inertia-vue-ts/vite.config.ts +2 -5
- metadata +19 -6
- data/stubs/hotwire/bin/vite +0 -27
- data/stubs/inertia-common/Procfile.dev +0 -3
- /data/stubs/{hotwire → default}/Procfile.dev +0 -0
- /data/stubs/hotwire/app/javascript/{alpinejs.js → alpinejs.stub} +0 -0
@@ -1,29 +1,32 @@
|
|
1
1
|
class Auth::AuthenticatedSessionController < ApplicationController
|
2
|
-
|
2
|
+
include RedirectIfAuthenticated
|
3
3
|
|
4
|
-
|
4
|
+
skip_authenticate only: %i[new create]
|
5
|
+
skip_redirect_if_authenticated only: %i[destroy]
|
6
|
+
|
7
|
+
layout 'guest'
|
5
8
|
|
6
9
|
def new
|
7
10
|
@form = Auth::LoginForm.new
|
8
11
|
|
9
|
-
render
|
12
|
+
render 'auth/login'
|
10
13
|
end
|
11
14
|
|
12
15
|
def create
|
13
16
|
@form = Auth::LoginForm.new params.permit(:email, :password)
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
return render "auth/login", status: :unprocessable_entity if user.nil?
|
18
|
+
@form.authenticate
|
18
19
|
|
19
|
-
login user
|
20
|
+
return render 'auth/login', status: :unprocessable_entity if Current.auth.user.nil?
|
20
21
|
|
21
22
|
redirect_to dashboard_path
|
22
23
|
end
|
23
24
|
|
24
25
|
def destroy
|
25
|
-
logout
|
26
|
+
Current.auth.logout
|
27
|
+
|
28
|
+
reset_session
|
26
29
|
|
27
|
-
redirect_to
|
30
|
+
redirect_to '/'
|
28
31
|
end
|
29
32
|
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
class Auth::NewPasswordController < ApplicationController
|
2
|
-
|
2
|
+
include RedirectIfAuthenticated
|
3
3
|
|
4
|
-
|
4
|
+
skip_authenticate
|
5
|
+
|
6
|
+
layout 'guest'
|
5
7
|
|
6
8
|
def new
|
7
9
|
@form = Auth::NewPasswordForm.new params.permit(:token)
|
8
10
|
|
9
|
-
render
|
11
|
+
render 'auth/reset_password'
|
10
12
|
end
|
11
13
|
|
12
14
|
def create
|
13
15
|
@form = Auth::NewPasswordForm.new params.permit(:token, :password, :password_confirmation)
|
14
16
|
|
15
|
-
return redirect_to login_path, flash: { status:
|
17
|
+
return redirect_to login_path, flash: { status: 'Your password has been reset.' } if @form.reset?
|
16
18
|
|
17
|
-
render
|
19
|
+
render 'auth/reset_password', status: :unprocessable_entity
|
18
20
|
end
|
19
21
|
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
class Auth::PasswordResetLinkController < ApplicationController
|
2
|
-
|
2
|
+
include RedirectIfAuthenticated
|
3
3
|
|
4
|
-
|
4
|
+
skip_authenticate
|
5
|
+
|
6
|
+
layout 'guest'
|
5
7
|
|
6
8
|
def new
|
7
9
|
@form = Auth::SendPasswordResetLinkForm.new
|
8
10
|
|
9
|
-
render
|
11
|
+
render 'auth/forgot_password'
|
10
12
|
end
|
11
13
|
|
12
14
|
def create
|
13
15
|
@form = Auth::SendPasswordResetLinkForm.new params.permit(:email)
|
14
16
|
|
15
|
-
return redirect_back_or_to password_request_path, flash: { status:
|
17
|
+
return redirect_back_or_to password_request_path, flash: { status: 'We have emailed your password reset link.' } if @form.send_reset_link?
|
16
18
|
|
17
|
-
render
|
19
|
+
render 'auth/forgot_password', status: :unprocessable_entity
|
18
20
|
end
|
19
21
|
end
|
@@ -1,22 +1,24 @@
|
|
1
1
|
class Auth::RegisteredUserController < ApplicationController
|
2
|
-
|
2
|
+
include RedirectIfAuthenticated
|
3
3
|
|
4
|
-
|
4
|
+
skip_authenticate
|
5
|
+
|
6
|
+
layout 'guest'
|
5
7
|
|
6
8
|
def new
|
7
9
|
@form = Auth::RegisterForm.new
|
8
10
|
|
9
|
-
render
|
11
|
+
render 'auth/register'
|
10
12
|
end
|
11
13
|
|
12
14
|
def create
|
13
15
|
@form = Auth::RegisterForm.new params.permit(:name, :email, :password, :password_confirmation)
|
14
16
|
|
15
|
-
return render
|
17
|
+
return render 'auth/register', status: :unprocessable_entity if @form.invalid?
|
16
18
|
|
17
19
|
user = User.create(name: @form.name, email: @form.email, password: @form.password)
|
18
20
|
|
19
|
-
login user
|
21
|
+
Current.auth.login user
|
20
22
|
|
21
23
|
redirect_to dashboard_path
|
22
24
|
end
|
@@ -2,33 +2,18 @@ module Authenticate
|
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
4
|
included do
|
5
|
-
before_action :
|
5
|
+
before_action :authenticate!
|
6
6
|
end
|
7
7
|
|
8
8
|
class_methods do
|
9
|
-
def
|
10
|
-
skip_before_action :
|
9
|
+
def skip_authenticate(**options)
|
10
|
+
skip_before_action :authenticate!, **options
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
-
def
|
17
|
-
|
18
|
-
Current.user = user
|
19
|
-
else
|
20
|
-
redirect_to login_path
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def login(user)
|
25
|
-
Current.user = user
|
26
|
-
reset_session
|
27
|
-
session[:user_id] = user.id
|
28
|
-
end
|
29
|
-
|
30
|
-
def logout
|
31
|
-
Current.user = nil
|
32
|
-
reset_session
|
16
|
+
def authenticate!
|
17
|
+
redirect_to login_path unless Current.auth.check?
|
33
18
|
end
|
34
19
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RedirectIfAuthenticated
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
before_action :redirect_if_authenticated!
|
6
|
+
end
|
7
|
+
|
8
|
+
class_methods do
|
9
|
+
def skip_redirect_if_authenticated(**options)
|
10
|
+
skip_before_action :redirect_if_authenticated!, **options
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def redirect_if_authenticated!
|
17
|
+
redirect_to dashboard_path if Current.auth.check?
|
18
|
+
end
|
19
|
+
end
|
@@ -2,10 +2,10 @@ class PasswordController < ApplicationController
|
|
2
2
|
def update
|
3
3
|
@update_password_form = UpdatePasswordForm.new params.permit(:current_password, :password, :password_confirmation)
|
4
4
|
|
5
|
-
return render partial:
|
5
|
+
return render partial: 'profile/partials/update_password_form', status: :unprocessable_entity if @update_password_form.invalid?
|
6
6
|
|
7
|
-
Current.user.update(password: @update_password_form.password)
|
7
|
+
Current.auth.user.update(password: @update_password_form.password)
|
8
8
|
|
9
|
-
redirect_back_or_to profile_edit_path, flash: { status:
|
9
|
+
redirect_back_or_to profile_edit_path, flash: { status: 'password-updated' }
|
10
10
|
end
|
11
11
|
end
|
@@ -1,33 +1,35 @@
|
|
1
1
|
class ProfileController < ApplicationController
|
2
2
|
def edit
|
3
|
-
@update_profile_information_form = UpdateProfileInformationForm.new(name: Current.user.name, email: Current.user.email)
|
3
|
+
@update_profile_information_form = UpdateProfileInformationForm.new(name: Current.auth.user.name, email: Current.auth.user.email)
|
4
4
|
@update_password_form = UpdatePasswordForm.new
|
5
5
|
@delete_user_form = DeleteUserForm.new
|
6
6
|
|
7
|
-
render
|
7
|
+
render 'profile/edit'
|
8
8
|
end
|
9
9
|
|
10
10
|
def update
|
11
11
|
@update_profile_information_form = UpdateProfileInformationForm.new params.permit(:name, :email)
|
12
12
|
|
13
|
-
return render partial:
|
13
|
+
return render partial: 'profile/partials/update_profile_information_form', status: :unprocessable_entity if @update_profile_information_form.invalid?
|
14
14
|
|
15
|
-
Current.user.update(name: @update_profile_information_form.name, email: @update_profile_information_form.email)
|
15
|
+
Current.auth.user.update(name: @update_profile_information_form.name, email: @update_profile_information_form.email)
|
16
16
|
|
17
|
-
redirect_to profile_edit_path, flash: { status:
|
17
|
+
redirect_to profile_edit_path, flash: { status: 'profile-updated' }
|
18
18
|
end
|
19
19
|
|
20
20
|
def destroy
|
21
21
|
@delete_user_form = DeleteUserForm.new params.permit(:password)
|
22
22
|
|
23
|
-
return render partial:
|
23
|
+
return render partial: 'profile/partials/delete_user_form', status: :unprocessable_entity if @delete_user_form.invalid?
|
24
24
|
|
25
|
-
user = Current.user
|
25
|
+
user = Current.auth.user
|
26
26
|
|
27
|
-
logout
|
27
|
+
Current.auth.logout
|
28
28
|
|
29
29
|
user.delete
|
30
30
|
|
31
|
-
|
31
|
+
reset_session
|
32
|
+
|
33
|
+
redirect_to '/'
|
32
34
|
end
|
33
35
|
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import
|
1
|
+
import '@hotwired/turbo-rails'
|
2
2
|
|
3
|
-
import Alpine from
|
3
|
+
import Alpine from 'alpinejs'
|
4
4
|
window.Alpine = Alpine
|
5
5
|
|
6
|
-
document.addEventListener(
|
6
|
+
document.addEventListener('DOMContentLoaded', function (event) {
|
7
7
|
window.Alpine.start()
|
8
8
|
})
|
@@ -1,23 +1,18 @@
|
|
1
1
|
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
|
2
|
-
|
2
|
+
Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.
|
3
3
|
</div>
|
4
|
-
|
5
4
|
<!-- Session Status -->
|
6
5
|
<%= render(AuthSessionStatusComponent.new({ class: "mb-4", status: flash[:status] })) %>
|
7
|
-
|
8
6
|
<%= form_with model: @form, url: password_request_path do |form| %>
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
Email Password Reset Link
|
21
|
-
<% end %>
|
22
|
-
</div>
|
7
|
+
<!-- Email Address -->
|
8
|
+
<div>
|
9
|
+
<%= render(InputLabelComponent.new({ for: "email", value: "Email" })) %>
|
10
|
+
<%= render(TextInputComponent.new({ id: "email", class: "block mt-1 w-full", type: "email", name: "email", value: @form.email, required: true, autofocus: true, autocomplete: "username" })) %>
|
11
|
+
<%= render(InputErrorComponent.new({ class: "mt-2", message: @form.error_messages[:email] })) %>
|
12
|
+
</div>
|
13
|
+
<div class="flex items-center justify-end mt-4">
|
14
|
+
<%= render(PrimaryButtonComponent.new) do %>
|
15
|
+
Email Password Reset Link
|
16
|
+
<% end %>
|
17
|
+
</div>
|
23
18
|
<% end %>
|
@@ -1,25 +1,18 @@
|
|
1
1
|
<!-- Session Status -->
|
2
2
|
<%= render(AuthSessionStatusComponent.new({ class: "mb-4", status: flash[:status] })) %>
|
3
|
-
|
4
3
|
<%= form_with model: @form, url: login_path do |form| %>
|
5
4
|
<!-- Email Address -->
|
6
5
|
<div>
|
7
6
|
<%= render(InputLabelComponent.new({ for: "email", value: "Email" })) %>
|
8
|
-
|
9
7
|
<%= render(TextInputComponent.new({ id: "email", class: "block mt-1 w-full", type: "email", name: "email", value: @form.email, required: true, autofocus: true, autocomplete: "username" })) %>
|
10
|
-
|
11
8
|
<%= render(InputErrorComponent.new({ class: "mt-2", message: @form.error_messages[:email] })) %>
|
12
9
|
</div>
|
13
|
-
|
14
10
|
<!-- Password -->
|
15
11
|
<div class="mt-4">
|
16
12
|
<%= render(InputLabelComponent.new({ for: "password", value: "Password" })) %>
|
17
|
-
|
18
13
|
<%= render(TextInputComponent.new({ id: "password", class: "block mt-1 w-full", type: "password", name: "password", required: true, autocomplete: "current-password" })) %>
|
19
|
-
|
20
14
|
<%= render(InputErrorComponent.new({ class: "mt-2", message: @form.error_messages[:password] })) %>
|
21
15
|
</div>
|
22
|
-
|
23
16
|
<!-- Remember Me -->
|
24
17
|
<div class="block mt-4">
|
25
18
|
<label for="remember_me" class="inline-flex items-center">
|
@@ -27,12 +20,10 @@
|
|
27
20
|
<span class="ms-2 text-sm text-gray-600 dark:text-gray-400">Remember me</span>
|
28
21
|
</label>
|
29
22
|
</div>
|
30
|
-
|
31
23
|
<div class="flex items-center justify-end mt-4">
|
32
24
|
<a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="<%= password_request_path %>">
|
33
25
|
Forgot your password?
|
34
26
|
</a>
|
35
|
-
|
36
27
|
<%= render(PrimaryButtonComponent.new({ class: "ms-4" })) do %>
|
37
28
|
Login
|
38
29
|
<% end %>
|
@@ -2,44 +2,31 @@
|
|
2
2
|
<!-- Name -->
|
3
3
|
<div>
|
4
4
|
<%= render(InputLabelComponent.new({ for: "name", value: "Name" })) %>
|
5
|
-
|
6
5
|
<%= render(TextInputComponent.new({ id: "name", class: "block mt-1 w-full", type: "text", name: "name", value: @form.name, required: true, autofocus: true, autocomplete: "name" })) %>
|
7
|
-
|
8
6
|
<%= render(InputErrorComponent.new({ class: "mt-2", message: @form.error_messages[:name] })) %>
|
9
7
|
</div>
|
10
|
-
|
11
8
|
<!-- Email Address -->
|
12
9
|
<div class="mt-4">
|
13
10
|
<%= render(InputLabelComponent.new({ for: "email", value: "Email" })) %>
|
14
|
-
|
15
11
|
<%= render(TextInputComponent.new({ id: "email", class: "block mt-1 w-full", type: "email", name: "email", value: @form.email, required: true, autocomplete: "username" })) %>
|
16
|
-
|
17
12
|
<%= render(InputErrorComponent.new({ class: "mt-2", message: @form.error_messages[:email] })) %>
|
18
13
|
</div>
|
19
|
-
|
20
14
|
<!-- Password -->
|
21
15
|
<div class="mt-4">
|
22
16
|
<%= render(InputLabelComponent.new({ for: "password", value: "Password" })) %>
|
23
|
-
|
24
17
|
<%= render(TextInputComponent.new({ id: "password", class: "block mt-1 w-full", type: "password", name: "password", required: true, autocomplete: "new-password" })) %>
|
25
|
-
|
26
18
|
<%= render(InputErrorComponent.new({ class: "mt-2", message: @form.error_messages[:password] })) %>
|
27
19
|
</div>
|
28
|
-
|
29
20
|
<!-- Confirm Password -->
|
30
21
|
<div class="mt-4">
|
31
22
|
<%= render(InputLabelComponent.new({ for: "password_confirmation", value: "Confirm Password" })) %>
|
32
|
-
|
33
23
|
<%= render(TextInputComponent.new({ id: "password_confirmation", class: "block mt-1 w-full", type: "password", name: "password_confirmation", required: true, autocomplete: "new-password" })) %>
|
34
|
-
|
35
24
|
<%= render(InputErrorComponent.new({ class: "mt-2", message: @form.error_messages[:password_confirmation] })) %>
|
36
25
|
</div>
|
37
|
-
|
38
26
|
<div class="flex items-center justify-end mt-4">
|
39
27
|
<a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="<%= login_path %>">
|
40
28
|
Already registered?
|
41
29
|
</a>
|
42
|
-
|
43
30
|
<%= render(PrimaryButtonComponent.new({ class: "ms-4" })) do %>
|
44
31
|
Register
|
45
32
|
<% end %>
|
@@ -1,25 +1,18 @@
|
|
1
1
|
<%= form_with model: @form, url: password_store_path do |form| %>
|
2
2
|
<!-- Password Reset Token -->
|
3
3
|
<input type="hidden" name="token" value="<%= @form.token %>">
|
4
|
-
|
5
4
|
<!-- Password -->
|
6
5
|
<div>
|
7
6
|
<%= render(InputLabelComponent.new({ for: "password", value: "Password" })) %>
|
8
|
-
|
9
7
|
<%= render(TextInputComponent.new({ id: "password", class: "block mt-1 w-full", type: "password", name: "password", required: true, autofocus: true, autocomplete: "new-password" })) %>
|
10
|
-
|
11
8
|
<%= render(InputErrorComponent.new({ class: "mt-2", message: @form.error_messages[:password] })) %>
|
12
9
|
</div>
|
13
|
-
|
14
10
|
<!-- Confirm Password -->
|
15
11
|
<div class="mt-4">
|
16
12
|
<%= render(InputLabelComponent.new({ for: "password_confirmation", value: "Confirm Password" })) %>
|
17
|
-
|
18
13
|
<%= render(TextInputComponent.new({ id: "password_confirmation", class: "block mt-1 w-full", type: "password", name: "password_confirmation", required: true, autocomplete: "new-password" })) %>
|
19
|
-
|
20
14
|
<%= render(InputErrorComponent.new({ class: "mt-2", message: @form.error_messages[:password_confirmation] })) %>
|
21
15
|
</div>
|
22
|
-
|
23
16
|
<div class="flex items-center justify-end mt-4">
|
24
17
|
<%= render(PrimaryButtonComponent.new) do %>
|
25
18
|
Reset Password
|
@@ -1,15 +1,14 @@
|
|
1
1
|
<% content_for(:header) do %>
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
3
|
+
Dashboard
|
4
|
+
</h2>
|
5
5
|
<% end %>
|
6
|
-
|
7
6
|
<div class="py-12">
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
</div>
|
7
|
+
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
8
|
+
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
9
|
+
<div class="p-6 text-gray-900 dark:text-gray-100">
|
10
|
+
You're logged in!
|
11
|
+
</div>
|
14
12
|
</div>
|
13
|
+
</div>
|
15
14
|
</div>
|
@@ -1,92 +1,82 @@
|
|
1
1
|
<nav x-data="{ open: false }" class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700">
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
</div>
|
12
|
-
|
13
|
-
<!-- Navigation Links -->
|
14
|
-
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
|
15
|
-
<%= render(NavLinkComponent.new({ href: dashboard_path })) do %>
|
16
|
-
Dashboard
|
17
|
-
<% end %>
|
18
|
-
</div>
|
19
|
-
</div>
|
20
|
-
|
21
|
-
<!-- Settings Dropdown -->
|
22
|
-
<div class="hidden sm:flex sm:items-center sm:ms-6">
|
23
|
-
<%= render DropdownComponent.new do |component| %>
|
24
|
-
<% component.with_trigger(classes: "") do %>
|
25
|
-
<button class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
|
26
|
-
<div><%= Current.user.name %></div>
|
27
|
-
|
28
|
-
<div class="ms-1">
|
29
|
-
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
30
|
-
<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" />
|
31
|
-
</svg>
|
32
|
-
</div>
|
33
|
-
</button>
|
34
|
-
<% end %>
|
35
|
-
|
36
|
-
<%= render(DropdownLinkComponent.new({ href: profile_edit_path })) do %>
|
37
|
-
Profile
|
38
|
-
<% end %>
|
39
|
-
|
40
|
-
<!-- Authentication -->
|
41
|
-
<form method="POST" action="<%= logout_path %>">
|
42
|
-
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
|
43
|
-
<%= render(DropdownLinkComponent.new({ href: logout_path, onclick: "event.preventDefault();this.closest('form').submit();" })) do %>
|
44
|
-
Log Out
|
45
|
-
<% end %>
|
46
|
-
</form>
|
47
|
-
<% end %>
|
48
|
-
</div>
|
49
|
-
|
50
|
-
<!-- Hamburger -->
|
51
|
-
<div class="-me-2 flex items-center sm:hidden">
|
52
|
-
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400 transition duration-150 ease-in-out">
|
53
|
-
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
54
|
-
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
55
|
-
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
56
|
-
</svg>
|
57
|
-
</button>
|
58
|
-
</div>
|
2
|
+
<!-- Primary Navigation Menu -->
|
3
|
+
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
4
|
+
<div class="flex justify-between h-16">
|
5
|
+
<div class="flex">
|
6
|
+
<!-- Logo -->
|
7
|
+
<div class="shrink-0 flex items-center">
|
8
|
+
<a href="/">
|
9
|
+
<%= render(ApplicationLogoComponent.new({ class: "block h-9 w-auto fill-current text-gray-800 dark:text-gray-200" })) %>
|
10
|
+
</a>
|
59
11
|
</div>
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
<%= render(ResponsiveNavLinkComponent.new({ href: dashboard_path })) do %>
|
66
|
-
Dashboard
|
67
|
-
<% end %>
|
68
|
-
</div>
|
69
|
-
|
70
|
-
<!-- Responsive Settings Options -->
|
71
|
-
<div class="pt-4 pb-1 border-t border-gray-200 dark:border-gray-600">
|
72
|
-
<div class="px-4">
|
73
|
-
<div class="font-medium text-base text-gray-800 dark:text-gray-200"><%= Current.user.name %></div>
|
74
|
-
<div class="font-medium text-sm text-gray-500"><%= Current.user.email %></div>
|
75
|
-
</div>
|
76
|
-
|
77
|
-
<div class="mt-3 space-y-1">
|
78
|
-
<%= render(ResponsiveNavLinkComponent.new({ href: profile_edit_path })) do %>
|
79
|
-
Profile
|
80
|
-
<% end %>
|
81
|
-
|
82
|
-
<!-- Authentication -->
|
83
|
-
<form method="POST" action="<%= logout_path %>">
|
84
|
-
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
|
85
|
-
<%= render(ResponsiveNavLinkComponent.new({ href: logout_path, onclick: "event.preventDefault();this.closest('form').submit();" })) do %>
|
86
|
-
Log Out
|
87
|
-
<% end %>
|
88
|
-
</form>
|
89
|
-
</div>
|
12
|
+
<!-- Navigation Links -->
|
13
|
+
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
|
14
|
+
<%= render(NavLinkComponent.new({ href: dashboard_path, active: current_page?(dashboard_path) })) do %>
|
15
|
+
Dashboard
|
16
|
+
<% end %>
|
90
17
|
</div>
|
18
|
+
</div>
|
19
|
+
<!-- Settings Dropdown -->
|
20
|
+
<div class="hidden sm:flex sm:items-center sm:ms-6">
|
21
|
+
<%= render DropdownComponent.new do |component| %>
|
22
|
+
<% component.with_trigger(classes: "") do %>
|
23
|
+
<button class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
|
24
|
+
<div><%= Current.auth.user.name %></div>
|
25
|
+
<div class="ms-1">
|
26
|
+
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
27
|
+
<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" />
|
28
|
+
</svg>
|
29
|
+
</div>
|
30
|
+
</button>
|
31
|
+
<% end %>
|
32
|
+
<%= render(DropdownLinkComponent.new({ href: profile_edit_path })) do %>
|
33
|
+
Profile
|
34
|
+
<% end %>
|
35
|
+
<!-- Authentication -->
|
36
|
+
<form method="POST" action="<%= logout_path %>">
|
37
|
+
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
|
38
|
+
<%= render(DropdownLinkComponent.new({ href: logout_path, onclick: "event.preventDefault();this.closest('form').submit()" })) do %>
|
39
|
+
Log Out
|
40
|
+
<% end %>
|
41
|
+
</form>
|
42
|
+
<% end %>
|
43
|
+
</div>
|
44
|
+
<!-- Hamburger -->
|
45
|
+
<div class="-me-2 flex items-center sm:hidden">
|
46
|
+
<button x-on:click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400 transition duration-150 ease-in-out">
|
47
|
+
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
48
|
+
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
49
|
+
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
50
|
+
</svg>
|
51
|
+
</button>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
<!-- Responsive Navigation Menu -->
|
56
|
+
<div :class="{'block': open, 'hidden': ! open}" class="hidden sm:hidden">
|
57
|
+
<div class="pt-2 pb-3 space-y-1">
|
58
|
+
<%= render(ResponsiveNavLinkComponent.new({ href: dashboard_path, active: current_page?(dashboard_path) })) do %>
|
59
|
+
Dashboard
|
60
|
+
<% end %>
|
61
|
+
</div>
|
62
|
+
<!-- Responsive Settings Options -->
|
63
|
+
<div class="pt-4 pb-1 border-t border-gray-200 dark:border-gray-600">
|
64
|
+
<div class="px-4">
|
65
|
+
<div class="font-medium text-base text-gray-800 dark:text-gray-200"><%= Current.auth.user.name %></div>
|
66
|
+
<div class="font-medium text-sm text-gray-500"><%= Current.auth.user.email %></div>
|
67
|
+
</div>
|
68
|
+
<div class="mt-3 space-y-1">
|
69
|
+
<%= render(ResponsiveNavLinkComponent.new({ href: profile_edit_path })) do %>
|
70
|
+
Profile
|
71
|
+
<% end %>
|
72
|
+
<!-- Authentication -->
|
73
|
+
<form method="POST" action="<%= logout_path %>">
|
74
|
+
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
|
75
|
+
<%= render(ResponsiveNavLinkComponent.new({ href: logout_path, onclick: "event.preventDefault();this.closest('form').submit()" })) do %>
|
76
|
+
Log Out
|
77
|
+
<% end %>
|
78
|
+
</form>
|
79
|
+
</div>
|
91
80
|
</div>
|
81
|
+
</div>
|
92
82
|
</nav>
|