kaze 0.8.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/kaze/commands/install_command.rb +3 -1
- data/lib/kaze/commands/installs_hotwire_stack.rb +2 -2
- data/lib/kaze/commands/installs_inertia_stacks.rb +7 -7
- data/lib/kaze/version.rb +1 -1
- data/stubs/default/app/forms/update_profile_information_form.rb +8 -0
- data/stubs/default/app/mailers/application_mailer.rb +1 -1
- data/stubs/default/app/mailers/user_mailer.rb +16 -1
- data/stubs/default/app/models/concerns/can_reset_password.rb +1 -1
- data/stubs/default/app/models/concerns/must_verify_email.rb +15 -0
- data/stubs/default/app/models/user.rb +1 -0
- data/stubs/default/app/views/user_mailer/reset_password.html.erb +2 -2
- data/stubs/default/app/views/user_mailer/verify_email.html.erb +33 -0
- data/stubs/default/config/routes.rb +4 -0
- data/stubs/default/db/migrate/20240101000000_create_users.rb +1 -0
- data/stubs/default/test/factories/users.rb +5 -0
- data/stubs/default/test/integration/auth/authentication_test.rb +4 -6
- data/stubs/default/test/integration/auth/email_verification_test.rb +40 -0
- data/stubs/default/test/integration/auth/password_reset_test.rb +3 -3
- data/stubs/default/test/integration/password_update_test.rb +2 -2
- data/stubs/default/test/integration/profile_test.rb +16 -4
- data/stubs/hotwire/app/components/modal_component.rb +5 -5
- data/stubs/hotwire/app/controllers/auth/authenticated_session_controller.rb +3 -2
- data/stubs/hotwire/app/controllers/auth/email_verification_notification_controller.rb +21 -0
- data/stubs/hotwire/app/controllers/auth/new_password_controller.rb +2 -2
- data/stubs/hotwire/app/controllers/auth/password_reset_link_controller.rb +1 -1
- data/stubs/hotwire/app/controllers/auth/registered_user_controller.rb +6 -2
- data/stubs/hotwire/app/controllers/auth/verified_email_controller.rb +23 -0
- data/stubs/hotwire/app/controllers/concerns/authenticate.rb +10 -0
- data/stubs/hotwire/app/controllers/concerns/validate_signature.rb +17 -0
- data/stubs/hotwire/app/controllers/password_controller.rb +3 -1
- data/stubs/hotwire/app/controllers/profile_controller.rb +5 -3
- data/stubs/hotwire/app/views/auth/verify_email.html.erb +23 -0
- data/stubs/hotwire/app/views/profile/partials/_delete_user_form.html.erb +1 -1
- data/stubs/hotwire/app/views/profile/partials/_update_profile_information_form.html.erb +18 -0
- data/stubs/inertia-common/app/controllers/auth/authenticated_session_controller.rb +3 -3
- data/stubs/inertia-common/app/controllers/auth/email_verification_notification_controller.rb +21 -0
- data/stubs/inertia-common/app/controllers/auth/new_password_controller.rb +2 -3
- data/stubs/inertia-common/app/controllers/auth/password_reset_link_controller.rb +3 -3
- data/stubs/inertia-common/app/controllers/auth/registered_user_controller.rb +6 -2
- data/stubs/inertia-common/app/controllers/auth/verified_email_controller.rb +23 -0
- data/stubs/inertia-common/app/controllers/concerns/authenticate.rb +10 -0
- data/stubs/inertia-common/app/controllers/concerns/validate_signature.rb +17 -0
- data/stubs/inertia-common/app/controllers/password_controller.rb +3 -1
- data/stubs/inertia-common/app/controllers/profile_controller.rb +7 -4
- data/stubs/inertia-common/test/integration/password_update_test.rb +2 -2
- data/stubs/inertia-common/test/integration/profile_test.rb +16 -4
- data/stubs/inertia-react-ts/app/javascript/Components/Checkbox.tsx +1 -4
- data/stubs/inertia-react-ts/app/javascript/Components/DangerButton.tsx +3 -5
- data/stubs/inertia-react-ts/app/javascript/Components/Dropdown.tsx +4 -25
- data/stubs/inertia-react-ts/app/javascript/Components/InputError.tsx +1 -4
- data/stubs/inertia-react-ts/app/javascript/Components/InputLabel.tsx +1 -4
- data/stubs/inertia-react-ts/app/javascript/Components/NavLink.tsx +3 -5
- data/stubs/inertia-react-ts/app/javascript/Components/PrimaryButton.tsx +3 -5
- data/stubs/inertia-react-ts/app/javascript/Components/SecondaryButton.tsx +3 -5
- data/stubs/inertia-react-ts/app/javascript/Components/TextInput.tsx +1 -7
- data/stubs/inertia-react-ts/app/javascript/Layouts/AuthenticatedLayout.tsx +14 -52
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ForgotPassword.tsx +4 -7
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Login.tsx +10 -24
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Register.tsx +2 -5
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ResetPassword.tsx +2 -5
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/VerifyEmail.tsx +47 -0
- data/stubs/inertia-react-ts/app/javascript/Pages/Dashboard.tsx +2 -8
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Edit.tsx +10 -10
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.tsx +10 -20
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.tsx +10 -18
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.tsx +35 -12
- data/stubs/inertia-react-ts/app/javascript/Pages/Welcome.tsx +1 -2
- data/stubs/inertia-react-ts/app/javascript/entrypoints/application.tsx +1 -5
- 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-react-ts/config/tailwind.config.js +1 -6
- data/stubs/inertia-vue-ts/app/javascript/Components/ApplicationLogo.vue +3 -1
- data/stubs/inertia-vue-ts/app/javascript/Components/Dropdown.vue +1 -4
- data/stubs/inertia-vue-ts/app/javascript/Components/Modal.vue +3 -13
- data/stubs/inertia-vue-ts/app/javascript/Layouts/AuthenticatedLayout.vue +10 -45
- data/stubs/inertia-vue-ts/app/javascript/Layouts/GuestLayout.vue +2 -6
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ForgotPassword.vue +4 -11
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Login.vue +2 -10
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Register.vue +1 -5
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ResetPassword.vue +2 -22
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/VerifyEmail.vue +50 -0
- data/stubs/inertia-vue-ts/app/javascript/Pages/Dashboard.vue +3 -11
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Edit.vue +2 -10
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.vue +5 -9
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.vue +2 -9
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.vue +26 -15
- data/stubs/inertia-vue-ts/app/javascript/Pages/Welcome.vue +2 -5
- 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
- data/stubs/inertia-vue-ts/config/tailwind.config.js +1 -6
- metadata +14 -2
@@ -16,9 +16,7 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
|
|
16
16
|
<template>
|
17
17
|
<div>
|
18
18
|
<div class="min-h-screen bg-gray-100 dark:bg-gray-900">
|
19
|
-
<nav
|
20
|
-
class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700"
|
21
|
-
>
|
19
|
+
<nav class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700">
|
22
20
|
<!-- Primary Navigation Menu -->
|
23
21
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
24
22
|
<div class="flex justify-between h-16">
|
@@ -26,20 +24,13 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
|
|
26
24
|
<!-- Logo -->
|
27
25
|
<div class="shrink-0 flex items-center">
|
28
26
|
<Link href="/">
|
29
|
-
<ApplicationLogo
|
30
|
-
class="block h-9 w-auto fill-current text-red-800 dark:text-red-200"
|
31
|
-
/>
|
27
|
+
<ApplicationLogo class="block h-9 w-auto fill-current text-red-800 dark:text-red-200" />
|
32
28
|
</Link>
|
33
29
|
</div>
|
34
30
|
|
35
31
|
<!-- Navigation Links -->
|
36
32
|
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
|
37
|
-
<NavLink
|
38
|
-
:href="dashboard_path()"
|
39
|
-
:active="pathname.match(/dashboard/) != null"
|
40
|
-
>
|
41
|
-
Dashboard
|
42
|
-
</NavLink>
|
33
|
+
<NavLink :href="dashboard_path()" :active="pathname.match(/dashboard/) != null"> Dashboard </NavLink>
|
43
34
|
</div>
|
44
35
|
</div>
|
45
36
|
|
@@ -72,16 +63,8 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
|
|
72
63
|
</template>
|
73
64
|
|
74
65
|
<template #content>
|
75
|
-
<DropdownLink :href="profile_edit_path()">
|
76
|
-
|
77
|
-
</DropdownLink>
|
78
|
-
<DropdownLink
|
79
|
-
:href="logout_path()"
|
80
|
-
method="post"
|
81
|
-
as="button"
|
82
|
-
>
|
83
|
-
Log Out
|
84
|
-
</DropdownLink>
|
66
|
+
<DropdownLink :href="profile_edit_path()"> Profile </DropdownLink>
|
67
|
+
<DropdownLink :href="logout_path()" method="post" as="button"> Log Out </DropdownLink>
|
85
68
|
</template>
|
86
69
|
</Dropdown>
|
87
70
|
</div>
|
@@ -93,12 +76,7 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
|
|
93
76
|
@click="showingNavigationDropdown = !showingNavigationDropdown"
|
94
77
|
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"
|
95
78
|
>
|
96
|
-
<svg
|
97
|
-
class="h-6 w-6"
|
98
|
-
stroke="currentColor"
|
99
|
-
fill="none"
|
100
|
-
viewBox="0 0 24 24"
|
101
|
-
>
|
79
|
+
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
102
80
|
<path
|
103
81
|
:class="{
|
104
82
|
hidden: showingNavigationDropdown,
|
@@ -134,10 +112,7 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
|
|
134
112
|
class="sm:hidden"
|
135
113
|
>
|
136
114
|
<div class="pt-2 pb-3 space-y-1">
|
137
|
-
<ResponsiveNavLink
|
138
|
-
:href="dashboard_path()"
|
139
|
-
:active="pathname.match(/dashboard/) != null"
|
140
|
-
>
|
115
|
+
<ResponsiveNavLink :href="dashboard_path()" :active="pathname.match(/dashboard/) != null">
|
141
116
|
Dashboard
|
142
117
|
</ResponsiveNavLink>
|
143
118
|
</div>
|
@@ -145,9 +120,7 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
|
|
145
120
|
<!-- Responsive Settings Options -->
|
146
121
|
<div class="pt-4 pb-1 border-t border-gray-200 dark:border-gray-600">
|
147
122
|
<div class="px-4">
|
148
|
-
<div
|
149
|
-
class="font-medium text-base text-gray-800 dark:text-gray-200"
|
150
|
-
>
|
123
|
+
<div class="font-medium text-base text-gray-800 dark:text-gray-200">
|
151
124
|
{{ $page.props.auth.user.name }}
|
152
125
|
</div>
|
153
126
|
<div class="font-medium text-sm text-gray-500">
|
@@ -156,16 +129,8 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
|
|
156
129
|
</div>
|
157
130
|
|
158
131
|
<div class="mt-3 space-y-1">
|
159
|
-
<ResponsiveNavLink :href="profile_edit_path()">
|
160
|
-
|
161
|
-
</ResponsiveNavLink>
|
162
|
-
<ResponsiveNavLink
|
163
|
-
:href="logout_path()"
|
164
|
-
method="post"
|
165
|
-
as="button"
|
166
|
-
>
|
167
|
-
Log Out
|
168
|
-
</ResponsiveNavLink>
|
132
|
+
<ResponsiveNavLink :href="profile_edit_path()"> Profile </ResponsiveNavLink>
|
133
|
+
<ResponsiveNavLink :href="logout_path()" method="post" as="button"> Log Out </ResponsiveNavLink>
|
169
134
|
</div>
|
170
135
|
</div>
|
171
136
|
</div>
|
@@ -4,18 +4,14 @@ import { Link } from '@inertiajs/vue3'
|
|
4
4
|
</script>
|
5
5
|
|
6
6
|
<template>
|
7
|
-
<div
|
8
|
-
class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900"
|
9
|
-
>
|
7
|
+
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900">
|
10
8
|
<div>
|
11
9
|
<Link href="/">
|
12
10
|
<ApplicationLogo class="w-20 h-20 fill-current text-red-500" />
|
13
11
|
</Link>
|
14
12
|
</div>
|
15
13
|
|
16
|
-
<div
|
17
|
-
class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-gray-800 shadow-md overflow-hidden sm:rounded-lg"
|
18
|
-
>
|
14
|
+
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-gray-800 shadow-md overflow-hidden sm:rounded-lg">
|
19
15
|
<slot />
|
20
16
|
</div>
|
21
17
|
</div>
|
@@ -25,15 +25,11 @@ const submit = () => {
|
|
25
25
|
<Head title="Forgot Password" />
|
26
26
|
|
27
27
|
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
|
28
|
-
Forgot your password? No problem. Just let us know your email address and
|
29
|
-
|
30
|
-
new one.
|
28
|
+
Forgot your password? No problem. Just let us know your email address and we will email you a password reset link
|
29
|
+
that will allow you to choose a new one.
|
31
30
|
</div>
|
32
31
|
|
33
|
-
<div
|
34
|
-
v-if="status"
|
35
|
-
class="mb-4 font-medium text-sm text-green-600 dark:text-green-400"
|
36
|
-
>
|
32
|
+
<div v-if="status" class="mb-4 font-medium text-sm text-green-600 dark:text-green-400">
|
37
33
|
{{ status }}
|
38
34
|
</div>
|
39
35
|
|
@@ -55,10 +51,7 @@ const submit = () => {
|
|
55
51
|
</div>
|
56
52
|
|
57
53
|
<div class="flex items-center justify-end mt-4">
|
58
|
-
<PrimaryButton
|
59
|
-
:class="{ 'opacity-25': form.processing }"
|
60
|
-
:disabled="form.processing"
|
61
|
-
>
|
54
|
+
<PrimaryButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
|
62
55
|
Email Password Reset Link
|
63
56
|
</PrimaryButton>
|
64
57
|
</div>
|
@@ -9,7 +9,6 @@ import { Head, Link, useForm } from '@inertiajs/vue3'
|
|
9
9
|
import { login_path, password_request_path } from '@/routes'
|
10
10
|
|
11
11
|
defineProps<{
|
12
|
-
canResetPassword?: boolean
|
13
12
|
status?: string
|
14
13
|
}>()
|
15
14
|
|
@@ -71,26 +70,19 @@ const submit = () => {
|
|
71
70
|
<div class="block mt-4">
|
72
71
|
<label class="flex items-center">
|
73
72
|
<Checkbox name="remember" v-model:checked="form.remember" />
|
74
|
-
<span class="ms-2 text-sm text-gray-600 dark:text-gray-400"
|
75
|
-
>Remember me</span
|
76
|
-
>
|
73
|
+
<span class="ms-2 text-sm text-gray-600 dark:text-gray-400">Remember me</span>
|
77
74
|
</label>
|
78
75
|
</div>
|
79
76
|
|
80
77
|
<div class="flex items-center justify-end mt-4">
|
81
78
|
<Link
|
82
|
-
v-if="canResetPassword"
|
83
79
|
:href="password_request_path()"
|
84
80
|
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"
|
85
81
|
>
|
86
82
|
Forgot your password?
|
87
83
|
</Link>
|
88
84
|
|
89
|
-
<PrimaryButton
|
90
|
-
class="ms-4"
|
91
|
-
:class="{ 'opacity-25': form.processing }"
|
92
|
-
:disabled="form.processing"
|
93
|
-
>
|
85
|
+
<PrimaryButton class="ms-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
|
94
86
|
Log in
|
95
87
|
</PrimaryButton>
|
96
88
|
</div>
|
@@ -97,11 +97,7 @@ const submit = () => {
|
|
97
97
|
Already registered?
|
98
98
|
</Link>
|
99
99
|
|
100
|
-
<PrimaryButton
|
101
|
-
class="ms-4"
|
102
|
-
:class="{ 'opacity-25': form.processing }"
|
103
|
-
:disabled="form.processing"
|
104
|
-
>
|
100
|
+
<PrimaryButton class="ms-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
|
105
101
|
Register
|
106
102
|
</PrimaryButton>
|
107
103
|
</div>
|
@@ -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
|
|
@@ -80,10 +63,7 @@ const submit = () => {
|
|
80
63
|
</div>
|
81
64
|
|
82
65
|
<div class="flex items-center justify-end mt-4">
|
83
|
-
<PrimaryButton
|
84
|
-
:class="{ 'opacity-25': form.processing }"
|
85
|
-
:disabled="form.processing"
|
86
|
-
>
|
66
|
+
<PrimaryButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
|
87
67
|
Reset Password
|
88
68
|
</PrimaryButton>
|
89
69
|
</div>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import { computed } from 'vue'
|
3
|
+
import GuestLayout from '@/Layouts/GuestLayout.vue'
|
4
|
+
import PrimaryButton from '@/Components/PrimaryButton.vue'
|
5
|
+
import { Head, Link, useForm } from '@inertiajs/vue3'
|
6
|
+
import { logout_path, verification_send_path } from '@/routes'
|
7
|
+
|
8
|
+
const props = defineProps<{
|
9
|
+
status?: string
|
10
|
+
}>()
|
11
|
+
|
12
|
+
const form = useForm({})
|
13
|
+
|
14
|
+
const submit = () => {
|
15
|
+
form.post(verification_send_path())
|
16
|
+
}
|
17
|
+
|
18
|
+
const verificationLinkSent = computed(() => props.status === 'verification-link-sent')
|
19
|
+
</script>
|
20
|
+
|
21
|
+
<template>
|
22
|
+
<GuestLayout>
|
23
|
+
<Head title="Email Verification" />
|
24
|
+
|
25
|
+
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
|
26
|
+
Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just
|
27
|
+
emailed to you? If you didn't receive the email, we will gladly send you another.
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div class="mb-4 font-medium text-sm text-green-600 dark:text-green-400" v-if="verificationLinkSent">
|
31
|
+
A new verification link has been sent to the email address you provided during registration.
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<form @submit.prevent="submit">
|
35
|
+
<div class="mt-4 flex items-center justify-between">
|
36
|
+
<PrimaryButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
|
37
|
+
Resend Verification Email
|
38
|
+
</PrimaryButton>
|
39
|
+
|
40
|
+
<Link
|
41
|
+
:href="logout_path()"
|
42
|
+
method="post"
|
43
|
+
as="button"
|
44
|
+
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"
|
45
|
+
>Log Out</Link
|
46
|
+
>
|
47
|
+
</div>
|
48
|
+
</form>
|
49
|
+
</GuestLayout>
|
50
|
+
</template>
|
@@ -8,21 +8,13 @@ import { Head } from '@inertiajs/vue3'
|
|
8
8
|
|
9
9
|
<AuthenticatedLayout>
|
10
10
|
<template #header>
|
11
|
-
<h2
|
12
|
-
class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight"
|
13
|
-
>
|
14
|
-
Dashboard
|
15
|
-
</h2>
|
11
|
+
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">Dashboard</h2>
|
16
12
|
</template>
|
17
13
|
|
18
14
|
<div class="py-12">
|
19
15
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
20
|
-
<div
|
21
|
-
class="
|
22
|
-
>
|
23
|
-
<div class="p-6 text-gray-900 dark:text-gray-100">
|
24
|
-
You're logged in!
|
25
|
-
</div>
|
16
|
+
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
17
|
+
<div class="p-6 text-gray-900 dark:text-gray-100">You're logged in!</div>
|
26
18
|
</div>
|
27
19
|
</div>
|
28
20
|
</div>
|
@@ -16,21 +16,13 @@ defineProps<{
|
|
16
16
|
|
17
17
|
<AuthenticatedLayout>
|
18
18
|
<template #header>
|
19
|
-
<h2
|
20
|
-
class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight"
|
21
|
-
>
|
22
|
-
Profile
|
23
|
-
</h2>
|
19
|
+
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">Profile</h2>
|
24
20
|
</template>
|
25
21
|
|
26
22
|
<div class="py-12">
|
27
23
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
28
24
|
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
29
|
-
<UpdateProfileInformationForm
|
30
|
-
:must-verify-email="mustVerifyEmail"
|
31
|
-
:status="status"
|
32
|
-
class="max-w-xl"
|
33
|
-
/>
|
25
|
+
<UpdateProfileInformationForm :must-verify-email="mustVerifyEmail" :status="status" class="max-w-xl" />
|
34
26
|
</div>
|
35
27
|
|
36
28
|
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
@@ -43,14 +43,11 @@ const closeModal = () => {
|
|
43
43
|
<template>
|
44
44
|
<section class="space-y-6">
|
45
45
|
<header>
|
46
|
-
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
47
|
-
Delete Account
|
48
|
-
</h2>
|
46
|
+
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">Delete Account</h2>
|
49
47
|
|
50
48
|
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
51
|
-
Once your account is deleted, all of its resources and data will be
|
52
|
-
|
53
|
-
data or information that you wish to retain.
|
49
|
+
Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your
|
50
|
+
account, please download any data or information that you wish to retain.
|
54
51
|
</p>
|
55
52
|
</header>
|
56
53
|
|
@@ -63,9 +60,8 @@ const closeModal = () => {
|
|
63
60
|
</h2>
|
64
61
|
|
65
62
|
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
66
|
-
Once your account is deleted, all of its resources and data will be
|
67
|
-
|
68
|
-
like to permanently delete your account.
|
63
|
+
Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your
|
64
|
+
password to confirm you would like to permanently delete your account.
|
69
65
|
</p>
|
70
66
|
|
71
67
|
<div class="mt-6">
|
@@ -39,9 +39,7 @@ const updatePassword = () => {
|
|
39
39
|
<template>
|
40
40
|
<section>
|
41
41
|
<header>
|
42
|
-
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
43
|
-
Update Password
|
44
|
-
</h2>
|
42
|
+
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">Update Password</h2>
|
45
43
|
|
46
44
|
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
47
45
|
Ensure your account is using a long, random password to stay secure.
|
@@ -102,12 +100,7 @@ const updatePassword = () => {
|
|
102
100
|
leave-active-class="transition ease-in-out"
|
103
101
|
leave-to-class="opacity-0"
|
104
102
|
>
|
105
|
-
<p
|
106
|
-
v-if="form.recentlySuccessful"
|
107
|
-
class="text-sm text-gray-600 dark:text-gray-400"
|
108
|
-
>
|
109
|
-
Saved.
|
110
|
-
</p>
|
103
|
+
<p v-if="form.recentlySuccessful" class="text-sm text-gray-600 dark:text-gray-400">Saved.</p>
|
111
104
|
</Transition>
|
112
105
|
</div>
|
113
106
|
</form>
|
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
|
@@ -22,19 +22,14 @@ const form = useForm({
|
|
22
22
|
<template>
|
23
23
|
<section>
|
24
24
|
<header>
|
25
|
-
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
26
|
-
Profile Information
|
27
|
-
</h2>
|
25
|
+
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">Profile Information</h2>
|
28
26
|
|
29
27
|
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
30
28
|
Update your account's profile information and email address.
|
31
29
|
</p>
|
32
30
|
</header>
|
33
31
|
|
34
|
-
<form
|
35
|
-
@submit.prevent="form.patch(profile_update_path())"
|
36
|
-
class="mt-6 space-y-6"
|
37
|
-
>
|
32
|
+
<form @submit.prevent="form.patch(profile_update_path())" class="mt-6 space-y-6">
|
38
33
|
<div>
|
39
34
|
<InputLabel for="name" value="Name" />
|
40
35
|
|
@@ -66,6 +61,27 @@ const form = useForm({
|
|
66
61
|
<InputError class="mt-2" :message="form.errors.email" />
|
67
62
|
</div>
|
68
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
|
+
|
69
85
|
<div class="flex items-center gap-4">
|
70
86
|
<PrimaryButton :disabled="form.processing">Save</PrimaryButton>
|
71
87
|
|
@@ -75,12 +91,7 @@ const form = useForm({
|
|
75
91
|
leave-active-class="transition ease-in-out"
|
76
92
|
leave-to-class="opacity-0"
|
77
93
|
>
|
78
|
-
<p
|
79
|
-
v-if="form.recentlySuccessful"
|
80
|
-
class="text-sm text-gray-600 dark:text-gray-400"
|
81
|
-
>
|
82
|
-
Saved.
|
83
|
-
</p>
|
94
|
+
<p v-if="form.recentlySuccessful" class="text-sm text-gray-600 dark:text-gray-400">Saved.</p>
|
84
95
|
</Transition>
|
85
96
|
</div>
|
86
97
|
</form>
|
@@ -18,9 +18,7 @@ defineProps<{
|
|
18
18
|
font-size: calc(0.9em + 0.5vw);
|
19
19
|
"
|
20
20
|
>
|
21
|
-
<header
|
22
|
-
class="absolute top-0 right-0 grid grid-cols-2 items-center gap-2 py-10 lg:grid-cols-3"
|
23
|
-
>
|
21
|
+
<header class="absolute top-0 right-0 grid grid-cols-2 items-center gap-2 py-10 lg:grid-cols-3">
|
24
22
|
<div class="-mx-3 flex flex-1 justify-end">
|
25
23
|
<Link
|
26
24
|
:href="dashboard_path()"
|
@@ -63,8 +61,7 @@ defineProps<{
|
|
63
61
|
target="_blank"
|
64
62
|
style="
|
65
63
|
transition: background 0.25s cubic-bezier(0.33, 1, 0.68, 1);
|
66
|
-
filter: drop-shadow(0 20px 13px rgb(0 0 0 / 0.03))
|
67
|
-
drop-shadow(0 8px 5px rgb(0 0 0 / 0.08));
|
64
|
+
filter: drop-shadow(0 20px 13px rgb(0 0 0 / 0.03)) drop-shadow(0 8px 5px rgb(0 0 0 / 0.08));
|
68
65
|
"
|
69
66
|
>
|
70
67
|
<img
|
@@ -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
|
+
}
|
@@ -3,12 +3,7 @@ import forms from '@tailwindcss/forms'
|
|
3
3
|
|
4
4
|
/** @type {import('tailwindcss').Config} */
|
5
5
|
export default {
|
6
|
-
content: [
|
7
|
-
'./public/*.html',
|
8
|
-
'./app/helpers/**/*.rb',
|
9
|
-
'./app/views/**/*',
|
10
|
-
'./app/javascript/**/*.vue',
|
11
|
-
],
|
6
|
+
content: ['./public/*.html', './app/helpers/**/*.rb', './app/views/**/*', './app/javascript/**/*.vue'],
|
12
7
|
|
13
8
|
theme: {
|
14
9
|
extend: {
|