kaze 0.9.0 → 0.10.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/version.rb +1 -1
- data/stubs/default/app/forms/update_profile_information_form.rb +8 -0
- data/stubs/default/config/routes.rb +1 -1
- data/stubs/default/test/integration/profile_test.rb +12 -0
- data/stubs/hotwire/app/controllers/concerns/validate_signature.rb +1 -1
- data/stubs/hotwire/app/controllers/password_controller.rb +2 -0
- data/stubs/hotwire/app/controllers/profile_controller.rb +3 -1
- data/stubs/hotwire/app/views/profile/partials/_update_profile_information_form.html.erb +18 -0
- data/stubs/inertia-common/app/controllers/auth/email_verification_notification_controller.rb +1 -1
- data/stubs/inertia-common/app/controllers/concerns/validate_signature.rb +1 -1
- data/stubs/inertia-common/app/controllers/password_controller.rb +2 -0
- data/stubs/inertia-common/app/controllers/profile_controller.rb +5 -2
- data/stubs/inertia-common/test/integration/profile_test.rb +12 -0
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ForgotPassword.tsx +2 -2
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Login.tsx +2 -2
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Register.tsx +1 -1
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ResetPassword.tsx +1 -1
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Edit.tsx +10 -6
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.tsx +6 -4
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.tsx +3 -3
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.tsx +38 -6
- data/stubs/inertia-react-ts/app/javascript/entrypoints/bootstrap.ts +3 -3
- data/stubs/inertia-react-ts/app/javascript/types/global.d.ts +4 -4
- data/stubs/inertia-react-ts/app/javascript/types/index.d.ts +8 -8
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ResetPassword.vue +1 -18
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.vue +23 -2
- data/stubs/inertia-vue-ts/app/javascript/entrypoints/application.ts +27 -23
- data/stubs/inertia-vue-ts/app/javascript/entrypoints/bootstrap.ts +3 -3
- data/stubs/inertia-vue-ts/app/javascript/types/global.d.ts +7 -7
- data/stubs/inertia-vue-ts/app/javascript/types/index.d.ts +8 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27a8de2c9dc1c9297b72ca20e60fc00582579e39cf1372ad019d6ab18c28942f
|
4
|
+
data.tar.gz: fadd95b9700cc5409c2cffcaae03ba3ad68cc79b8331b6a9e27612a47d6e5ce7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5bd8c23395b302a93fa836e33c10da76de5681d563f84c1f16ff70317583aa3470e05d03cdfd726257c0ece38ef20c8d72ffe0974e0cbdb14d93a7688a1686c
|
7
|
+
data.tar.gz: 70cd7f58402805e19197e0c9f161ebde8891e5696eafdec0c96dc3017c52fe6f966068329c77f3f55a3e989cc983050694d91a68097502691fed80e4ea4084c0
|
data/lib/kaze/version.rb
CHANGED
@@ -3,4 +3,12 @@ class UpdateProfileInformationForm < ApplicationForm
|
|
3
3
|
|
4
4
|
validates :name, presence: true
|
5
5
|
validates :email, presence: true, lowercase: true, email: true, uniqueness: { model: User, attribute: :email, conditions: -> { where.not(id: Current.auth.user.id) } }
|
6
|
+
|
7
|
+
def update
|
8
|
+
Current.auth.user.name = name
|
9
|
+
Current.auth.user.email = email
|
10
|
+
Current.auth.user.email_verified_at = nil if Current.auth.user.changed.include?('email')
|
11
|
+
|
12
|
+
Current.auth.user.save
|
13
|
+
end
|
6
14
|
end
|
@@ -16,7 +16,7 @@ Rails.application.routes.draw do
|
|
16
16
|
post 'reset-password', to: 'auth/new_password#create', as: :password_store
|
17
17
|
|
18
18
|
get 'verify-email', to: 'auth/email_verification_notification#new', as: :verification_notice
|
19
|
-
post 'email
|
19
|
+
post 'verify-email', to: 'auth/email_verification_notification#create', as: :verification_send
|
20
20
|
get 'verify-email/:id/:hash', to: 'auth/verified_email#create', as: :verification_verify
|
21
21
|
|
22
22
|
post 'logout', to: 'auth/authenticated_session#destroy', as: :logout
|
@@ -25,6 +25,18 @@ class ProfileTest < ActionDispatch::IntegrationTest
|
|
25
25
|
assert_equal 'test@example.com', user.email
|
26
26
|
end
|
27
27
|
|
28
|
+
test 'email verification status is unchanged when the email address is unchanged' do
|
29
|
+
user = FactoryBot.create(:user)
|
30
|
+
|
31
|
+
acting_as(user).patch profile_edit_path, params: {
|
32
|
+
name: 'Test User',
|
33
|
+
email: user.email
|
34
|
+
}
|
35
|
+
|
36
|
+
assert_redirected_to profile_edit_path
|
37
|
+
assert_not user.reload.email_verified_at.blank?
|
38
|
+
end
|
39
|
+
|
28
40
|
test 'user can delete their account' do
|
29
41
|
user = FactoryBot.create(:user)
|
30
42
|
|
@@ -3,7 +3,7 @@ module ValidateSignature
|
|
3
3
|
|
4
4
|
included do
|
5
5
|
before_action do
|
6
|
-
render file: "#{Rails.root}/public/404.html",
|
6
|
+
render file: "#{Rails.root}/public/404.html", layout: false, status: :not_found unless has_valid_signature?
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
@@ -1,4 +1,6 @@
|
|
1
1
|
class ProfileController < ApplicationController
|
2
|
+
skip_ensure_email_is_verified
|
3
|
+
|
2
4
|
def edit
|
3
5
|
@update_profile_information_form = UpdateProfileInformationForm.new(name: Current.auth.user.name, email: Current.auth.user.email)
|
4
6
|
@update_password_form = UpdatePasswordForm.new
|
@@ -12,7 +14,7 @@ class ProfileController < ApplicationController
|
|
12
14
|
|
13
15
|
return render partial: 'profile/partials/update_profile_information_form', status: :unprocessable_entity if @update_profile_information_form.invalid?
|
14
16
|
|
15
|
-
|
17
|
+
@update_profile_information_form.update
|
16
18
|
|
17
19
|
redirect_to profile_edit_path, flash: { status: 'profile-updated' }
|
18
20
|
end
|
@@ -8,6 +8,9 @@
|
|
8
8
|
Update your account's profile information and email address.
|
9
9
|
</p>
|
10
10
|
</header>
|
11
|
+
<form id="send-verification" method="post" action="<%= verification_send_path %>">
|
12
|
+
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
|
13
|
+
</form>
|
11
14
|
<%= form_with model: @update_profile_information_form, url: profile_update_path, method: "patch", class: "mt-6 space-y-6" do %>
|
12
15
|
<!-- Name -->
|
13
16
|
<div>
|
@@ -20,6 +23,21 @@
|
|
20
23
|
<%= render(InputLabelComponent.new({ for: "email", value: "Email" })) %>
|
21
24
|
<%= render(TextInputComponent.new({ id: "email", class: "block mt-1 w-full", type: "email", name: "email", value: @update_profile_information_form.email, required: true, autocomplete: "username" })) %>
|
22
25
|
<%= render(InputErrorComponent.new({ class: "mt-2", message: @update_profile_information_form.error_messages[:email] })) %>
|
26
|
+
<% if User.include?(MustVerifyEmail) && !Current.auth.user.has_verified_email? %>
|
27
|
+
<div>
|
28
|
+
<p class="text-sm mt-2 text-gray-800 dark:text-gray-200">
|
29
|
+
Your email address is unverified.
|
30
|
+
<button form="send-verification" 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">
|
31
|
+
Click here to re-send the verification email.
|
32
|
+
</button>
|
33
|
+
</p>
|
34
|
+
<% if flash[:status] == 'verification-link-sent' %>
|
35
|
+
<p class="mt-2 font-medium text-sm text-green-600 dark:text-green-400">
|
36
|
+
A new verification link has been sent to your email address.
|
37
|
+
</p>
|
38
|
+
<% end %>
|
39
|
+
</div>
|
40
|
+
<% end %>
|
23
41
|
</div>
|
24
42
|
<div class="flex items-center gap-4">
|
25
43
|
<%= render(PrimaryButtonComponent.new) do %>
|
data/stubs/inertia-common/app/controllers/auth/email_verification_notification_controller.rb
CHANGED
@@ -16,6 +16,6 @@ class Auth::EmailVerificationNotificationController < ApplicationController
|
|
16
16
|
|
17
17
|
Current.auth.user.send_email_verification_notification
|
18
18
|
|
19
|
-
redirect_back_or_to
|
19
|
+
redirect_back_or_to verification_notice_path, flash: { status: 'verification-link-sent' }
|
20
20
|
end
|
21
21
|
end
|
@@ -3,7 +3,7 @@ module ValidateSignature
|
|
3
3
|
|
4
4
|
included do
|
5
5
|
before_action do
|
6
|
-
render file: "#{Rails.root}/public/404.html",
|
6
|
+
render file: "#{Rails.root}/public/404.html", layout: false, status: :not_found unless has_valid_signature?
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
@@ -1,7 +1,10 @@
|
|
1
1
|
class ProfileController < ApplicationController
|
2
|
+
skip_ensure_email_is_verified
|
3
|
+
|
2
4
|
def edit
|
3
5
|
render inertia: 'Profile/Edit', props: {
|
4
|
-
|
6
|
+
mustVerifyEmail: User.include?(MustVerifyEmail),
|
7
|
+
status: flash[:status]
|
5
8
|
}
|
6
9
|
end
|
7
10
|
|
@@ -10,7 +13,7 @@ class ProfileController < ApplicationController
|
|
10
13
|
|
11
14
|
return redirect_to profile_edit_path, inertia: { errors: form.error_messages } if form.invalid?
|
12
15
|
|
13
|
-
|
16
|
+
form.update
|
14
17
|
|
15
18
|
redirect_to profile_edit_path
|
16
19
|
end
|
@@ -25,6 +25,18 @@ class ProfileTest < ActionDispatch::IntegrationTest
|
|
25
25
|
assert_equal 'test@example.com', user.email
|
26
26
|
end
|
27
27
|
|
28
|
+
test 'email verification status is unchanged when the email address is unchanged' do
|
29
|
+
user = FactoryBot.create(:user)
|
30
|
+
|
31
|
+
acting_as(user).patch profile_edit_path, params: {
|
32
|
+
name: 'Test User',
|
33
|
+
email: user.email
|
34
|
+
}
|
35
|
+
|
36
|
+
assert_redirected_to profile_edit_path
|
37
|
+
assert_not user.reload.email_verified_at.blank?
|
38
|
+
end
|
39
|
+
|
28
40
|
test 'user can delete their account' do
|
29
41
|
user = FactoryBot.create(:user)
|
30
42
|
|
@@ -21,12 +21,12 @@ export default function ForgotPassword({ status }: { status?: string }) {
|
|
21
21
|
<GuestLayout>
|
22
22
|
<Head title="Forgot Password" />
|
23
23
|
|
24
|
-
<div className="mb-4 text-sm text-gray-600">
|
24
|
+
<div className="mb-4 text-sm text-gray-600 dark:text-gray-400">
|
25
25
|
Forgot your password? No problem. Just let us know your email address and we will email you a password reset
|
26
26
|
link that will allow you to choose a new one.
|
27
27
|
</div>
|
28
28
|
|
29
|
-
{status && <div className="mb-4 font-medium text-sm text-green-600">{status}</div>}
|
29
|
+
{status && <div className="mb-4 font-medium text-sm text-green-600 dark:text-green-400">{status}</div>}
|
30
30
|
|
31
31
|
<form onSubmit={submit}>
|
32
32
|
<TextInput
|
@@ -70,14 +70,14 @@ export default function Login({ status }: { status?: string }) {
|
|
70
70
|
<div className="block mt-4">
|
71
71
|
<label className="flex items-center">
|
72
72
|
<Checkbox name="remember" checked={data.remember} onChange={(e) => setData('remember', e.target.checked)} />
|
73
|
-
<span className="ms-2 text-sm text-gray-600">Remember me</span>
|
73
|
+
<span className="ms-2 text-sm text-gray-600 dark:text-gray-400">Remember me</span>
|
74
74
|
</label>
|
75
75
|
</div>
|
76
76
|
|
77
77
|
<div className="flex items-center justify-end mt-4">
|
78
78
|
<Link
|
79
79
|
href={password_request_path()}
|
80
|
-
className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
80
|
+
className="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"
|
81
81
|
>
|
82
82
|
Forgot your password?
|
83
83
|
</Link>
|
@@ -103,7 +103,7 @@ export default function Register() {
|
|
103
103
|
<div className="flex items-center justify-end mt-4">
|
104
104
|
<Link
|
105
105
|
href={login_path()}
|
106
|
-
className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
106
|
+
className="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"
|
107
107
|
>
|
108
108
|
Already registered?
|
109
109
|
</Link>
|
@@ -5,25 +5,29 @@ import UpdateProfileInformationForm from './Partials/UpdateProfileInformationFor
|
|
5
5
|
import { Head } from '@inertiajs/react'
|
6
6
|
import { PageProps } from '@/types'
|
7
7
|
|
8
|
-
export default function Edit({
|
8
|
+
export default function Edit({
|
9
|
+
auth,
|
10
|
+
mustVerifyEmail,
|
11
|
+
status,
|
12
|
+
}: PageProps<{ mustVerifyEmail: boolean; status?: string }>) {
|
9
13
|
return (
|
10
14
|
<AuthenticatedLayout
|
11
15
|
user={auth.user}
|
12
|
-
header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Profile</h2>}
|
16
|
+
header={<h2 className="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">Profile</h2>}
|
13
17
|
>
|
14
18
|
<Head title="Profile" />
|
15
19
|
|
16
20
|
<div className="py-12">
|
17
21
|
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
18
|
-
<div className="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
|
19
|
-
<UpdateProfileInformationForm className="max-w-xl" />
|
22
|
+
<div className="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
23
|
+
<UpdateProfileInformationForm mustVerifyEmail={mustVerifyEmail} status={status} className="max-w-xl" />
|
20
24
|
</div>
|
21
25
|
|
22
|
-
<div className="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
|
26
|
+
<div className="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
23
27
|
<UpdatePasswordForm className="max-w-xl" />
|
24
28
|
</div>
|
25
29
|
|
26
|
-
<div className="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
|
30
|
+
<div className="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
27
31
|
<DeleteUserForm className="max-w-xl" />
|
28
32
|
</div>
|
29
33
|
</div>
|
@@ -47,9 +47,9 @@ export default function DeleteUserForm({ className = '' }: { className?: string
|
|
47
47
|
return (
|
48
48
|
<section className={`space-y-6 ${className}`}>
|
49
49
|
<header>
|
50
|
-
<h2 className="text-lg font-medium text-gray-900">Delete Account</h2>
|
50
|
+
<h2 className="text-lg font-medium text-gray-900 dark:text-gray-100">Delete Account</h2>
|
51
51
|
|
52
|
-
<p className="mt-1 text-sm text-gray-600">
|
52
|
+
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
53
53
|
Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your
|
54
54
|
account, please download any data or information that you wish to retain.
|
55
55
|
</p>
|
@@ -59,9 +59,11 @@ export default function DeleteUserForm({ className = '' }: { className?: string
|
|
59
59
|
|
60
60
|
<Modal show={confirmingUserDeletion} onClose={closeModal}>
|
61
61
|
<form onSubmit={deleteUser} className="p-6">
|
62
|
-
<h2 className="text-lg font-medium text-gray-900">
|
62
|
+
<h2 className="text-lg font-medium text-gray-900 dark:text-gray-100">
|
63
|
+
Are you sure you want to delete your account?
|
64
|
+
</h2>
|
63
65
|
|
64
|
-
<p className="mt-1 text-sm text-gray-600">
|
66
|
+
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
65
67
|
Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your
|
66
68
|
password to confirm you would like to permanently delete your account.
|
67
69
|
</p>
|
@@ -40,9 +40,9 @@ export default function UpdatePasswordForm({ className = '' }: { className?: str
|
|
40
40
|
return (
|
41
41
|
<section className={className}>
|
42
42
|
<header>
|
43
|
-
<h2 className="text-lg font-medium text-gray-900">Update Password</h2>
|
43
|
+
<h2 className="text-lg font-medium text-gray-900 dark:text-gray-100">Update Password</h2>
|
44
44
|
|
45
|
-
<p className="mt-1 text-sm text-gray-600">
|
45
|
+
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
46
46
|
Ensure your account is using a long, random password to stay secure.
|
47
47
|
</p>
|
48
48
|
</header>
|
@@ -105,7 +105,7 @@ export default function UpdatePasswordForm({ className = '' }: { className?: str
|
|
105
105
|
leave="transition ease-in-out"
|
106
106
|
leaveTo="opacity-0"
|
107
107
|
>
|
108
|
-
<p className="text-sm text-gray-600">Saved.</p>
|
108
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">Saved.</p>
|
109
109
|
</Transition>
|
110
110
|
</div>
|
111
111
|
</form>
|
data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.tsx
CHANGED
@@ -2,13 +2,21 @@ import InputError from '@/Components/InputError'
|
|
2
2
|
import InputLabel from '@/Components/InputLabel'
|
3
3
|
import PrimaryButton from '@/Components/PrimaryButton'
|
4
4
|
import TextInput from '@/Components/TextInput'
|
5
|
-
import { useForm, usePage } from '@inertiajs/react'
|
5
|
+
import { Link, useForm, usePage } from '@inertiajs/react'
|
6
6
|
import { Transition } from '@headlessui/react'
|
7
7
|
import { FormEventHandler } from 'react'
|
8
8
|
import { PageProps } from '@/types'
|
9
|
-
import { profile_update_path } from '@/routes'
|
9
|
+
import { profile_update_path, verification_send_path } from '@/routes'
|
10
10
|
|
11
|
-
export default function UpdateProfileInformation({
|
11
|
+
export default function UpdateProfileInformation({
|
12
|
+
mustVerifyEmail,
|
13
|
+
status,
|
14
|
+
className = '',
|
15
|
+
}: {
|
16
|
+
mustVerifyEmail: boolean
|
17
|
+
status?: string
|
18
|
+
className?: string
|
19
|
+
}) {
|
12
20
|
const user = usePage<PageProps>().props.auth.user
|
13
21
|
|
14
22
|
const { data, setData, patch, errors, processing, recentlySuccessful } = useForm({
|
@@ -25,9 +33,11 @@ export default function UpdateProfileInformation({ className = '' }: { className
|
|
25
33
|
return (
|
26
34
|
<section className={className}>
|
27
35
|
<header>
|
28
|
-
<h2 className="text-lg font-medium text-gray-900">Profile Information</h2>
|
36
|
+
<h2 className="text-lg font-medium text-gray-900 dark:text-gray-100">Profile Information</h2>
|
29
37
|
|
30
|
-
<p className="mt-1 text-sm text-gray-600">
|
38
|
+
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
39
|
+
Update your account's profile information and email address.
|
40
|
+
</p>
|
31
41
|
</header>
|
32
42
|
|
33
43
|
<form onSubmit={submit} className="mt-6 space-y-6">
|
@@ -63,6 +73,28 @@ export default function UpdateProfileInformation({ className = '' }: { className
|
|
63
73
|
<InputError className="mt-2" message={errors.email} />
|
64
74
|
</div>
|
65
75
|
|
76
|
+
{mustVerifyEmail && user.email_verified_at === null && (
|
77
|
+
<div>
|
78
|
+
<p className="text-sm mt-2 text-gray-800 dark:text-gray-200">
|
79
|
+
Your email address is unverified.
|
80
|
+
<Link
|
81
|
+
href={verification_send_path()}
|
82
|
+
method="post"
|
83
|
+
as="button"
|
84
|
+
className="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"
|
85
|
+
>
|
86
|
+
Click here to re-send the verification email.
|
87
|
+
</Link>
|
88
|
+
</p>
|
89
|
+
|
90
|
+
{status === 'verification-link-sent' && (
|
91
|
+
<div className="mt-2 font-medium text-sm text-green-600 dark:text-green-400">
|
92
|
+
A new verification link has been sent to your email address.
|
93
|
+
</div>
|
94
|
+
)}
|
95
|
+
</div>
|
96
|
+
)}
|
97
|
+
|
66
98
|
<div className="flex items-center gap-4">
|
67
99
|
<PrimaryButton disabled={processing}>Save</PrimaryButton>
|
68
100
|
|
@@ -73,7 +105,7 @@ export default function UpdateProfileInformation({ className = '' }: { className
|
|
73
105
|
leave="transition ease-in-out"
|
74
106
|
leaveTo="opacity-0"
|
75
107
|
>
|
76
|
-
<p className="text-sm text-gray-600">Saved.</p>
|
108
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">Saved.</p>
|
77
109
|
</Transition>
|
78
110
|
</div>
|
79
111
|
</form>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import axios from 'axios'
|
2
|
-
window.axios = axios
|
1
|
+
import axios from 'axios'
|
2
|
+
window.axios = axios
|
3
3
|
|
4
|
-
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
|
4
|
+
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
|
@@ -1,12 +1,12 @@
|
|
1
1
|
export interface User {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
id: number
|
3
|
+
name: string
|
4
|
+
email: string
|
5
|
+
email_verified_at: string
|
6
6
|
}
|
7
7
|
|
8
8
|
export type PageProps<T extends Record<string, unknown> = Record<string, unknown>> = T & {
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
}
|
9
|
+
auth: {
|
10
|
+
user: User
|
11
|
+
}
|
12
|
+
}
|
@@ -8,13 +8,11 @@ import { Head, useForm } from '@inertiajs/vue3'
|
|
8
8
|
import { password_store_path } from '@/routes'
|
9
9
|
|
10
10
|
const props = defineProps<{
|
11
|
-
email: string
|
12
11
|
token: string
|
13
12
|
}>()
|
14
13
|
|
15
14
|
const form = useForm({
|
16
15
|
token: props.token,
|
17
|
-
email: props.email,
|
18
16
|
password: '',
|
19
17
|
password_confirmation: '',
|
20
18
|
})
|
@@ -34,22 +32,6 @@ const submit = () => {
|
|
34
32
|
|
35
33
|
<form @submit.prevent="submit">
|
36
34
|
<div>
|
37
|
-
<InputLabel for="email" value="Email" />
|
38
|
-
|
39
|
-
<TextInput
|
40
|
-
id="email"
|
41
|
-
type="email"
|
42
|
-
class="mt-1 block w-full"
|
43
|
-
v-model="form.email"
|
44
|
-
required
|
45
|
-
autofocus
|
46
|
-
autocomplete="username"
|
47
|
-
/>
|
48
|
-
|
49
|
-
<InputError class="mt-2" :message="form.errors.email" />
|
50
|
-
</div>
|
51
|
-
|
52
|
-
<div class="mt-4">
|
53
35
|
<InputLabel for="password" value="Password" />
|
54
36
|
|
55
37
|
<TextInput
|
@@ -58,6 +40,7 @@ const submit = () => {
|
|
58
40
|
class="mt-1 block w-full"
|
59
41
|
v-model="form.password"
|
60
42
|
required
|
43
|
+
autofocus
|
61
44
|
autocomplete="new-password"
|
62
45
|
/>
|
63
46
|
|
data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.vue
CHANGED
@@ -3,8 +3,8 @@ import InputError from '@/Components/InputError.vue'
|
|
3
3
|
import InputLabel from '@/Components/InputLabel.vue'
|
4
4
|
import PrimaryButton from '@/Components/PrimaryButton.vue'
|
5
5
|
import TextInput from '@/Components/TextInput.vue'
|
6
|
-
import { useForm, usePage } from '@inertiajs/vue3'
|
7
|
-
import { profile_update_path } from '@/routes'
|
6
|
+
import { Link, useForm, usePage } from '@inertiajs/vue3'
|
7
|
+
import { profile_update_path, verification_send_path } from '@/routes'
|
8
8
|
|
9
9
|
defineProps<{
|
10
10
|
mustVerifyEmail?: Boolean
|
@@ -61,6 +61,27 @@ const form = useForm({
|
|
61
61
|
<InputError class="mt-2" :message="form.errors.email" />
|
62
62
|
</div>
|
63
63
|
|
64
|
+
<div v-if="mustVerifyEmail && user.email_verified_at === null">
|
65
|
+
<p class="text-sm mt-2 text-gray-800 dark:text-gray-200">
|
66
|
+
Your email address is unverified.
|
67
|
+
<Link
|
68
|
+
:href="verification_send_path()"
|
69
|
+
method="post"
|
70
|
+
as="button"
|
71
|
+
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"
|
72
|
+
>
|
73
|
+
Click here to re-send the verification email.
|
74
|
+
</Link>
|
75
|
+
</p>
|
76
|
+
|
77
|
+
<div
|
78
|
+
v-show="status === 'verification-link-sent'"
|
79
|
+
class="mt-2 font-medium text-sm text-green-600 dark:text-green-400"
|
80
|
+
>
|
81
|
+
A new verification link has been sent to your email address.
|
82
|
+
</div>
|
83
|
+
</div>
|
84
|
+
|
64
85
|
<div class="flex items-center gap-4">
|
65
86
|
<PrimaryButton :disabled="form.processing">Save</PrimaryButton>
|
66
87
|
|
@@ -1,34 +1,38 @@
|
|
1
1
|
import './bootstrap'
|
2
2
|
import '../../assets/builds/tailwind.css'
|
3
3
|
|
4
|
-
import { createApp, h, DefineComponent } from 'vue'
|
5
|
-
import { createInertiaApp } from '@inertiajs/vue3'
|
4
|
+
import { createApp, h, DefineComponent } from 'vue'
|
5
|
+
import { createInertiaApp } from '@inertiajs/vue3'
|
6
6
|
|
7
|
-
async function resolvePageComponent<T>(
|
8
|
-
|
9
|
-
|
7
|
+
async function resolvePageComponent<T>(
|
8
|
+
path: string | string[],
|
9
|
+
pages: Record<string, Promise<T> | (() => Promise<T>)>,
|
10
|
+
): Promise<T> {
|
11
|
+
for (const p of Array.isArray(path) ? path : [path]) {
|
12
|
+
const page = pages[p]
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
}
|
14
|
-
|
15
|
-
return typeof page === 'function' ? page() : page
|
14
|
+
if (typeof page === 'undefined') {
|
15
|
+
continue
|
16
16
|
}
|
17
17
|
|
18
|
-
|
18
|
+
return typeof page === 'function' ? page() : page
|
19
|
+
}
|
20
|
+
|
21
|
+
throw new Error(`Page not found: ${path}`)
|
19
22
|
}
|
20
23
|
|
21
|
-
const appName = import.meta.env.VITE_APP_NAME || 'Rails'
|
24
|
+
const appName = import.meta.env.VITE_APP_NAME || 'Rails'
|
22
25
|
|
23
26
|
createInertiaApp({
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
}
|
27
|
+
title: (title) => `${title} - ${appName}`,
|
28
|
+
resolve: (name) =>
|
29
|
+
resolvePageComponent(`../Pages/${name}.vue`, import.meta.glob<DefineComponent>('../Pages/**/*.vue')),
|
30
|
+
setup({ el, App, props, plugin }) {
|
31
|
+
createApp({ render: () => h(App, props) })
|
32
|
+
.use(plugin)
|
33
|
+
.mount(el)
|
34
|
+
},
|
35
|
+
progress: {
|
36
|
+
color: '#4B5563',
|
37
|
+
},
|
38
|
+
})
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import axios from 'axios'
|
2
|
-
window.axios = axios
|
1
|
+
import axios from 'axios'
|
2
|
+
window.axios = axios
|
3
3
|
|
4
|
-
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
|
4
|
+
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
|
@@ -1,13 +1,13 @@
|
|
1
|
-
import { PageProps as InertiaPageProps } from '@inertiajs/core'
|
2
|
-
import { AxiosInstance } from 'axios'
|
3
|
-
import { PageProps as AppPageProps } from './'
|
1
|
+
import { PageProps as InertiaPageProps } from '@inertiajs/core'
|
2
|
+
import { AxiosInstance } from 'axios'
|
3
|
+
import { PageProps as AppPageProps } from './'
|
4
4
|
|
5
5
|
declare global {
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
interface Window {
|
7
|
+
axios: AxiosInstance
|
8
|
+
}
|
9
9
|
}
|
10
10
|
|
11
11
|
declare module '@inertiajs/core' {
|
12
|
-
|
12
|
+
interface PageProps extends InertiaPageProps, AppPageProps {}
|
13
13
|
}
|
@@ -1,12 +1,12 @@
|
|
1
1
|
export interface User {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
id: number
|
3
|
+
name: string
|
4
|
+
email: string
|
5
|
+
email_verified_at: string
|
6
6
|
}
|
7
7
|
|
8
8
|
export type PageProps<T extends Record<string, unknown> = Record<string, unknown>> = T & {
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
}
|
9
|
+
auth: {
|
10
|
+
user: User
|
11
|
+
}
|
12
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kaze
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cuong Giang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|