betterstart-cli 0.0.98 → 0.0.100
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.
- package/dist/assets/adapters/next/templates/init/api/upload-route.ts +2 -1
- package/dist/assets/adapters/next/templates/init/components/layouts/admin-settings-sidebar.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/components/layouts/admin-sign-out.tsx +27 -8
- package/dist/assets/adapters/next/templates/init/components/shared/data-table/data-table.tsx +3 -1
- package/dist/assets/adapters/next/templates/init/components/shared/delete-dialog.tsx +3 -2
- package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-version-restore-dialog.tsx +4 -3
- package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-versions-button.tsx +5 -2
- package/dist/assets/adapters/next/templates/init/components/shared/media/edit-media-dialog-content.tsx +11 -5
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-delete-dialog.tsx +6 -4
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-delete-drawer.tsx +12 -8
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-empty-state.tsx +6 -5
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-grid-pagination.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-url-importer.tsx +5 -3
- package/dist/assets/adapters/next/templates/init/components/shared/search-input.tsx +2 -0
- package/dist/assets/adapters/next/templates/init/components/shared/sort-order-dialog.tsx +12 -7
- package/dist/assets/adapters/next/templates/init/hooks/use-entity-versions.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/cleanup-audit-logs.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/forms/upsert-form-settings.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/media/create-media.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media-bulk.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/media/update-media.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/profile/change-own-password.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/profile/update-email.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/upload/upload-media-from-url.ts +2 -2
- package/dist/assets/adapters/next/templates/init/lib/actions/users/change-user-password.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/create-user.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/delete-user.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/update-user-role.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/create-webhook.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/delete-webhook.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/get-webhook-secret.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/regenerate-webhook-secret.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/send-test-webhook.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/update-webhook.ts +2 -1
- package/dist/assets/adapters/next/templates/init/pages/forgot-password-form.tsx +7 -7
- package/dist/assets/adapters/next/templates/init/pages/login-form.tsx +7 -7
- package/dist/assets/adapters/next/templates/init/pages/login-page.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/pages/media/media-page-content.tsx +5 -4
- package/dist/assets/adapters/next/templates/init/pages/profile/profile-form.tsx +13 -10
- package/dist/assets/adapters/next/templates/init/pages/reset-password-form.tsx +5 -5
- package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-table.tsx +3 -1
- package/dist/assets/adapters/next/templates/init/pages/settings/forms/form-notifications-drawer.tsx +10 -5
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/delete-webhook-dialog.tsx +19 -10
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhook-actions.tsx +9 -4
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhook-endpoint-dialog.tsx +26 -20
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhooks-logs-page-content.tsx +4 -4
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhooks-logs-table.tsx +3 -1
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhooks-table.tsx +3 -1
- package/dist/assets/adapters/next/templates/init/pages/users/change-password-dialog.tsx +6 -5
- package/dist/assets/adapters/next/templates/init/pages/users/create-user-dialog.tsx +5 -5
- package/dist/assets/adapters/next/templates/init/pages/users/delete-user-dialog.tsx +6 -4
- package/dist/assets/adapters/next/templates/init/pages/users/edit-role-dialog.tsx +9 -5
- package/dist/assets/adapters/next/templates/init/pages/users/users-table.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/utils/error/action-error.ts +35 -0
- package/dist/assets/shared-assets/react-admin/schema.json +8 -0
- package/dist/assets/shared-assets/react-admin/ui/sonner.tsx +3 -8
- package/dist/assets/shared-assets/react-admin/ui/spinner.tsx +1 -1
- package/dist/{chunk-AIQWGMU7.js → chunk-45Z6XDG5.js} +419 -83
- package/dist/chunk-45Z6XDG5.js.map +1 -0
- package/dist/cli.js +2027 -2391
- package/dist/cli.js.map +1 -1
- package/dist/{template-reader-F2VFSDKV.js → template-reader-J6G7N5V6.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-AIQWGMU7.js.map +0 -1
- /package/dist/{template-reader-F2VFSDKV.js.map → template-reader-J6G7N5V6.js.map} +0 -0
|
@@ -7,6 +7,7 @@ import { requireRole, UserRole } from '@admin/auth/middleware'
|
|
|
7
7
|
import db from '@admin/db'
|
|
8
8
|
import { user } from '@admin/db/schema'
|
|
9
9
|
import { runAdminEventHooks } from '@admin/lib/lifecycle-hooks'
|
|
10
|
+
import { toActionError } from '@admin/utils/error/action-error'
|
|
10
11
|
import { eq } from 'drizzle-orm'
|
|
11
12
|
import { updateTag } from 'next/cache'
|
|
12
13
|
import { headers } from 'next/headers'
|
|
@@ -71,7 +72,7 @@ export async function changeUserPassword(
|
|
|
71
72
|
} catch (error) {
|
|
72
73
|
return {
|
|
73
74
|
success: false,
|
|
74
|
-
error: error
|
|
75
|
+
error: toActionError(error, 'Failed to change user password')
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
}
|
|
@@ -8,6 +8,7 @@ import db from '@admin/db'
|
|
|
8
8
|
import { user } from '@admin/db/schema'
|
|
9
9
|
import { runAdminEventHooks } from '@admin/lib/lifecycle-hooks'
|
|
10
10
|
import { getTouchedFieldNames } from '@admin/utils/audit/audit'
|
|
11
|
+
import { toActionError } from '@admin/utils/error/action-error'
|
|
11
12
|
import { eq } from 'drizzle-orm'
|
|
12
13
|
import { updateTag } from 'next/cache'
|
|
13
14
|
import { usersCacheTags } from './types'
|
|
@@ -67,7 +68,7 @@ export async function createUser(input: CreateUserInput): Promise<CreateUserResu
|
|
|
67
68
|
} catch (error) {
|
|
68
69
|
return {
|
|
69
70
|
success: false,
|
|
70
|
-
error: error
|
|
71
|
+
error: toActionError(error, 'Failed to create user')
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
}
|
|
@@ -6,6 +6,7 @@ import { requireRole, UserRole } from '@admin/auth/middleware'
|
|
|
6
6
|
import db from '@admin/db'
|
|
7
7
|
import { user } from '@admin/db/schema'
|
|
8
8
|
import { runAdminEventHooks } from '@admin/lib/lifecycle-hooks'
|
|
9
|
+
import { toActionError } from '@admin/utils/error/action-error'
|
|
9
10
|
import { eq } from 'drizzle-orm'
|
|
10
11
|
import { updateTag } from 'next/cache'
|
|
11
12
|
import { usersCacheTags } from './types'
|
|
@@ -40,7 +41,7 @@ export async function deleteUser(userId: string): Promise<DeleteUserResult> {
|
|
|
40
41
|
} catch (error) {
|
|
41
42
|
return {
|
|
42
43
|
success: false,
|
|
43
|
-
error: error
|
|
44
|
+
error: toActionError(error, 'Failed to delete user')
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
}
|
|
@@ -6,6 +6,7 @@ import { requireRole, UserRole } from '@admin/auth/middleware'
|
|
|
6
6
|
import db from '@admin/db'
|
|
7
7
|
import { user } from '@admin/db/schema'
|
|
8
8
|
import { runAdminEventHooks } from '@admin/lib/lifecycle-hooks'
|
|
9
|
+
import { toActionError } from '@admin/utils/error/action-error'
|
|
9
10
|
import { eq } from 'drizzle-orm'
|
|
10
11
|
import { updateTag } from 'next/cache'
|
|
11
12
|
import { usersCacheTags } from './types'
|
|
@@ -44,7 +45,7 @@ export async function updateUserRole(
|
|
|
44
45
|
} catch (error) {
|
|
45
46
|
return {
|
|
46
47
|
success: false,
|
|
47
|
-
error: error
|
|
48
|
+
error: toActionError(error, 'Failed to update user role')
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
}
|
|
@@ -4,6 +4,7 @@ import type { CreateWebhookInput, WebhookResult } from './types'
|
|
|
4
4
|
import { requireRole, UserRole } from '@admin/auth/middleware'
|
|
5
5
|
import db from '@admin/db'
|
|
6
6
|
import { webhookSubscriptions, webhooks } from '@admin/db/schema'
|
|
7
|
+
import { toActionError } from '@admin/utils/error/action-error'
|
|
7
8
|
import { generateWebhookSecret } from '@admin/utils/webhook/signature'
|
|
8
9
|
import { updateTag } from 'next/cache'
|
|
9
10
|
import { webhooksCacheTags } from './types'
|
|
@@ -49,7 +50,7 @@ export async function createWebhook(input: CreateWebhookInput): Promise<WebhookR
|
|
|
49
50
|
console.error('Error creating webhook:', error)
|
|
50
51
|
return {
|
|
51
52
|
success: false,
|
|
52
|
-
error: error
|
|
53
|
+
error: toActionError(error, 'Failed to create webhook')
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
}
|
|
@@ -4,6 +4,7 @@ import type { WebhookResult } from './types'
|
|
|
4
4
|
import { requireRole, UserRole } from '@admin/auth/middleware'
|
|
5
5
|
import db from '@admin/db'
|
|
6
6
|
import { webhooks } from '@admin/db/schema'
|
|
7
|
+
import { toActionError } from '@admin/utils/error/action-error'
|
|
7
8
|
import { eq } from 'drizzle-orm'
|
|
8
9
|
import { updateTag } from 'next/cache'
|
|
9
10
|
import { webhooksCacheTags } from './types'
|
|
@@ -20,7 +21,7 @@ export async function deleteWebhook(id: string): Promise<WebhookResult> {
|
|
|
20
21
|
console.error('Error deleting webhook:', error)
|
|
21
22
|
return {
|
|
22
23
|
success: false,
|
|
23
|
-
error: error
|
|
24
|
+
error: toActionError(error, 'Failed to delete webhook')
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
}
|
|
@@ -4,6 +4,7 @@ import type { WebhookSecretResult } from './types'
|
|
|
4
4
|
import { requireRole, UserRole } from '@admin/auth/middleware'
|
|
5
5
|
import db from '@admin/db'
|
|
6
6
|
import { webhooks } from '@admin/db/schema'
|
|
7
|
+
import { toActionError } from '@admin/utils/error/action-error'
|
|
7
8
|
import { eq } from 'drizzle-orm'
|
|
8
9
|
|
|
9
10
|
export async function getWebhookSecret(id: string): Promise<WebhookSecretResult> {
|
|
@@ -22,7 +23,7 @@ export async function getWebhookSecret(id: string): Promise<WebhookSecretResult>
|
|
|
22
23
|
console.error('Error fetching webhook secret:', error)
|
|
23
24
|
return {
|
|
24
25
|
success: false,
|
|
25
|
-
error: error
|
|
26
|
+
error: toActionError(error, 'Failed to fetch webhook secret')
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
}
|
package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/regenerate-webhook-secret.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { WebhookSecretResult } from './types'
|
|
|
4
4
|
import { requireRole, UserRole } from '@admin/auth/middleware'
|
|
5
5
|
import db from '@admin/db'
|
|
6
6
|
import { webhooks } from '@admin/db/schema'
|
|
7
|
+
import { toActionError } from '@admin/utils/error/action-error'
|
|
7
8
|
import { generateWebhookSecret } from '@admin/utils/webhook/signature'
|
|
8
9
|
import { eq } from 'drizzle-orm'
|
|
9
10
|
import { updateTag } from 'next/cache'
|
|
@@ -29,7 +30,7 @@ export async function regenerateWebhookSecret(id: string): Promise<WebhookSecret
|
|
|
29
30
|
console.error('Error regenerating webhook secret:', error)
|
|
30
31
|
return {
|
|
31
32
|
success: false,
|
|
32
|
-
error: error
|
|
33
|
+
error: toActionError(error, 'Failed to regenerate webhook secret')
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
}
|
|
@@ -4,6 +4,7 @@ import type { SendTestWebhookResult } from './types'
|
|
|
4
4
|
import { requireRole, UserRole } from '@admin/auth/middleware'
|
|
5
5
|
import db from '@admin/db'
|
|
6
6
|
import { webhooks } from '@admin/db/schema'
|
|
7
|
+
import { toActionError } from '@admin/utils/error/action-error'
|
|
7
8
|
import { createWebhookEventId, signWebhookPayload } from '@admin/utils/webhook/signature'
|
|
8
9
|
import { eq } from 'drizzle-orm'
|
|
9
10
|
import { recordWebhookDelivery } from './dispatch'
|
|
@@ -75,7 +76,7 @@ export async function sendTestWebhook(id: string): Promise<SendTestWebhookResult
|
|
|
75
76
|
console.error('Error sending test webhook:', error)
|
|
76
77
|
return {
|
|
77
78
|
success: false,
|
|
78
|
-
error: error
|
|
79
|
+
error: toActionError(error, 'Failed to send test webhook')
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
}
|
|
@@ -4,6 +4,7 @@ import type { UpdateWebhookInput, WebhookResult } from './types'
|
|
|
4
4
|
import { requireRole, UserRole } from '@admin/auth/middleware'
|
|
5
5
|
import db from '@admin/db'
|
|
6
6
|
import { webhookSubscriptions, webhooks } from '@admin/db/schema'
|
|
7
|
+
import { toActionError } from '@admin/utils/error/action-error'
|
|
7
8
|
import { and, eq, notInArray } from 'drizzle-orm'
|
|
8
9
|
import { updateTag } from 'next/cache'
|
|
9
10
|
import { webhooksCacheTags } from './types'
|
|
@@ -66,7 +67,7 @@ export async function updateWebhook(id: string, input: UpdateWebhookInput): Prom
|
|
|
66
67
|
console.error('Error updating webhook:', error)
|
|
67
68
|
return {
|
|
68
69
|
success: false,
|
|
69
|
-
error: error
|
|
70
|
+
error: toActionError(error, 'Failed to update webhook')
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
}
|
|
@@ -7,8 +7,8 @@ import { Button } from '@admin/components/ui/button'
|
|
|
7
7
|
import { Card, CardContent } from '@admin/components/ui/card'
|
|
8
8
|
import { Field, FieldGroup, FieldLabel } from '@admin/components/ui/field'
|
|
9
9
|
import { Input } from '@admin/components/ui/input'
|
|
10
|
+
import { Spinner } from '@admin/components/ui/spinner'
|
|
10
11
|
import { cn } from '@admin/utils/shared/cn'
|
|
11
|
-
import { LoaderCircle } from 'lucide-react'
|
|
12
12
|
import Image from 'next/image'
|
|
13
13
|
import Link from 'next/link'
|
|
14
14
|
|
|
@@ -39,7 +39,7 @@ export function ForgotPasswordForm({ className, ...props }: React.ComponentProps
|
|
|
39
39
|
}
|
|
40
40
|
setSuccess(true)
|
|
41
41
|
} catch {
|
|
42
|
-
setError('
|
|
42
|
+
setError('Failed to send the reset link. Try again.')
|
|
43
43
|
}
|
|
44
44
|
})
|
|
45
45
|
}
|
|
@@ -68,7 +68,7 @@ export function ForgotPasswordForm({ className, ...props }: React.ComponentProps
|
|
|
68
68
|
</p>
|
|
69
69
|
</div>
|
|
70
70
|
<Link href="/admin/login" className="text-sm underline-offset-4 hover:underline">
|
|
71
|
-
Back to
|
|
71
|
+
Back to sign in
|
|
72
72
|
</Link>
|
|
73
73
|
</FieldGroup>
|
|
74
74
|
) : (
|
|
@@ -101,16 +101,16 @@ export function ForgotPasswordForm({ className, ...props }: React.ComponentProps
|
|
|
101
101
|
/>
|
|
102
102
|
</Field>
|
|
103
103
|
<Field className="pt-4">
|
|
104
|
-
<Button type="submit" disabled={isPending}>
|
|
105
|
-
{isPending && <
|
|
106
|
-
{isPending ? 'Sending
|
|
104
|
+
<Button type="submit" disabled={isPending} aria-busy={isPending}>
|
|
105
|
+
{isPending && <Spinner />}
|
|
106
|
+
{isPending ? 'Sending…' : 'Send Reset Link'}
|
|
107
107
|
</Button>
|
|
108
108
|
</Field>
|
|
109
109
|
<Link
|
|
110
110
|
href="/admin/login"
|
|
111
111
|
className="text-center text-sm underline-offset-4 hover:underline"
|
|
112
112
|
>
|
|
113
|
-
Back to
|
|
113
|
+
Back to sign in
|
|
114
114
|
</Link>
|
|
115
115
|
</div>
|
|
116
116
|
</FieldGroup>
|
|
@@ -6,9 +6,9 @@ import { Button } from '@admin/components/ui/button'
|
|
|
6
6
|
import { Card, CardContent } from '@admin/components/ui/card'
|
|
7
7
|
import { Field, FieldGroup, FieldLabel } from '@admin/components/ui/field'
|
|
8
8
|
import { Input } from '@admin/components/ui/input'
|
|
9
|
+
import { Spinner } from '@admin/components/ui/spinner'
|
|
9
10
|
import { getAdminPostLoginPath } from '@admin/utils/auth/roles'
|
|
10
11
|
import { cn } from '@admin/utils/shared/cn'
|
|
11
|
-
import { LoaderCircle } from 'lucide-react'
|
|
12
12
|
import Image from 'next/image'
|
|
13
13
|
import Link from 'next/link'
|
|
14
14
|
import { useRouter } from 'next/navigation'
|
|
@@ -45,7 +45,7 @@ export function LoginForm({ className, ...props }: React.ComponentProps<'div'>)
|
|
|
45
45
|
router.replace(getAdminPostLoginPath(role))
|
|
46
46
|
router.refresh()
|
|
47
47
|
} catch {
|
|
48
|
-
setError('
|
|
48
|
+
setError('Failed to sign you in. Try again.')
|
|
49
49
|
}
|
|
50
50
|
})
|
|
51
51
|
}
|
|
@@ -67,11 +67,11 @@ export function LoginForm({ className, ...props }: React.ComponentProps<'div'>)
|
|
|
67
67
|
<FieldGroup className="gap-10 pb-12">
|
|
68
68
|
<div className="flex flex-col items-start">
|
|
69
69
|
<h1 className="text-xl font-medium">Welcome back</h1>
|
|
70
|
-
<p className="text-balance text-muted-foreground">
|
|
70
|
+
<p className="text-balance text-muted-foreground">Sign in to your account</p>
|
|
71
71
|
</div>
|
|
72
72
|
{resetSuccess ? (
|
|
73
73
|
<div className="rounded-md bg-emerald-500/10 p-3 text-sm text-emerald-700 dark:text-emerald-400">
|
|
74
|
-
Password reset
|
|
74
|
+
Password reset. Sign in with your new password.
|
|
75
75
|
</div>
|
|
76
76
|
) : null}
|
|
77
77
|
{error ? (
|
|
@@ -116,9 +116,9 @@ export function LoginForm({ className, ...props }: React.ComponentProps<'div'>)
|
|
|
116
116
|
/>
|
|
117
117
|
</Field>
|
|
118
118
|
<Field className="pt-4">
|
|
119
|
-
<Button type="submit" disabled={isPending}>
|
|
120
|
-
{isPending && <
|
|
121
|
-
{isPending ? 'Signing in
|
|
119
|
+
<Button type="submit" disabled={isPending} aria-busy={isPending}>
|
|
120
|
+
{isPending && <Spinner />}
|
|
121
|
+
{isPending ? 'Signing in…' : 'Sign in'}
|
|
122
122
|
</Button>
|
|
123
123
|
</Field>
|
|
124
124
|
</div>
|
|
@@ -156,12 +156,13 @@ export function MediaPageContent() {
|
|
|
156
156
|
mutationFn: (ids: string[]) => deleteMediaBulk(ids),
|
|
157
157
|
onSuccess: (result, ids) => {
|
|
158
158
|
if (result.success) {
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
toast.success(
|
|
160
|
+
ids.length === 1 ? '1 media item deleted' : `${ids.length} media items deleted`
|
|
161
|
+
)
|
|
161
162
|
void setSelectedIds([])
|
|
162
163
|
queryClient.invalidateQueries({ queryKey: ['media'] })
|
|
163
164
|
} else {
|
|
164
|
-
toast.error(result.error ?? 'Failed to delete
|
|
165
|
+
toast.error(result.error ?? 'Failed to delete the selected media')
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
168
|
})
|
|
@@ -169,7 +170,7 @@ export function MediaPageContent() {
|
|
|
169
170
|
return (
|
|
170
171
|
<React.Fragment>
|
|
171
172
|
<PageHeader
|
|
172
|
-
title="Media
|
|
173
|
+
title="Media"
|
|
173
174
|
actions={
|
|
174
175
|
<Tabs defaultValue="upload">
|
|
175
176
|
<TabsList>
|
|
@@ -29,8 +29,8 @@ import {
|
|
|
29
29
|
FormMessage
|
|
30
30
|
} from '@admin/components/ui/form'
|
|
31
31
|
import { Input } from '@admin/components/ui/input'
|
|
32
|
+
import { Spinner } from '@admin/components/ui/spinner'
|
|
32
33
|
import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'
|
|
33
|
-
import { LoaderCircle } from 'lucide-react'
|
|
34
34
|
import { useRouter } from 'next/navigation'
|
|
35
35
|
import { useForm } from 'react-hook-form'
|
|
36
36
|
import { toast } from 'sonner'
|
|
@@ -139,7 +139,7 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
139
139
|
})
|
|
140
140
|
router.refresh()
|
|
141
141
|
} catch {
|
|
142
|
-
toast.error('
|
|
142
|
+
toast.error('Failed to update your profile. Try again.')
|
|
143
143
|
}
|
|
144
144
|
})
|
|
145
145
|
}
|
|
@@ -164,7 +164,7 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
164
164
|
confirmPassword: ''
|
|
165
165
|
})
|
|
166
166
|
} catch {
|
|
167
|
-
toast.error('
|
|
167
|
+
toast.error('Failed to change your password. Try again.')
|
|
168
168
|
}
|
|
169
169
|
})
|
|
170
170
|
}
|
|
@@ -187,7 +187,7 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
187
187
|
}
|
|
188
188
|
toast.success('Check your email for a password reset link')
|
|
189
189
|
} catch {
|
|
190
|
-
toast.error('
|
|
190
|
+
toast.error('Failed to send the reset link. Try again.')
|
|
191
191
|
}
|
|
192
192
|
})
|
|
193
193
|
}
|
|
@@ -297,10 +297,11 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
297
297
|
<Button
|
|
298
298
|
type="submit"
|
|
299
299
|
disabled={profilePending || !profileForm.formState.isDirty}
|
|
300
|
+
aria-busy={profilePending}
|
|
300
301
|
className="ml-auto min-w-25"
|
|
301
302
|
>
|
|
302
|
-
{profilePending && <
|
|
303
|
-
{profilePending ? 'Saving
|
|
303
|
+
{profilePending && <Spinner />}
|
|
304
|
+
{profilePending ? 'Saving…' : 'Save'}
|
|
304
305
|
</Button>
|
|
305
306
|
</CardFooter>
|
|
306
307
|
</Card>
|
|
@@ -375,10 +376,11 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
375
376
|
<Button
|
|
376
377
|
type="submit"
|
|
377
378
|
disabled={passwordPending || !passwordForm.formState.isDirty}
|
|
379
|
+
aria-busy={passwordPending}
|
|
378
380
|
className="ml-auto min-w-25"
|
|
379
381
|
>
|
|
380
|
-
{passwordPending && <
|
|
381
|
-
{passwordPending ? 'Changing
|
|
382
|
+
{passwordPending && <Spinner />}
|
|
383
|
+
{passwordPending ? 'Changing…' : 'Change Password'}
|
|
382
384
|
</Button>
|
|
383
385
|
</CardFooter>
|
|
384
386
|
</Card>
|
|
@@ -401,10 +403,11 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
401
403
|
type="button"
|
|
402
404
|
className="ml-auto min-w-25"
|
|
403
405
|
disabled={resetPending}
|
|
406
|
+
aria-busy={resetPending}
|
|
404
407
|
onClick={handleResetPassword}
|
|
405
408
|
>
|
|
406
|
-
{resetPending && <
|
|
407
|
-
{resetPending ? 'Sending
|
|
409
|
+
{resetPending && <Spinner />}
|
|
410
|
+
{resetPending ? 'Sending…' : 'Reset Password'}
|
|
408
411
|
</Button>
|
|
409
412
|
</CardFooter>
|
|
410
413
|
</Card>
|
|
@@ -6,8 +6,8 @@ import { Button } from '@admin/components/ui/button'
|
|
|
6
6
|
import { Card, CardContent } from '@admin/components/ui/card'
|
|
7
7
|
import { Field, FieldGroup, FieldLabel } from '@admin/components/ui/field'
|
|
8
8
|
import { Input } from '@admin/components/ui/input'
|
|
9
|
+
import { Spinner } from '@admin/components/ui/spinner'
|
|
9
10
|
import { cn } from '@admin/utils/shared/cn'
|
|
10
|
-
import { LoaderCircle } from 'lucide-react'
|
|
11
11
|
import Image from 'next/image'
|
|
12
12
|
import Link from 'next/link'
|
|
13
13
|
import { useRouter } from 'next/navigation'
|
|
@@ -89,7 +89,7 @@ export function ResetPasswordForm({ className, ...props }: React.ComponentProps<
|
|
|
89
89
|
await authClient.getSession({ query: { disableCookieCache: true } })
|
|
90
90
|
router.push(serializeLoginUrl('/admin/login', { reset: 'success' }))
|
|
91
91
|
} catch {
|
|
92
|
-
setError('
|
|
92
|
+
setError('Failed to reset your password. Try again.')
|
|
93
93
|
}
|
|
94
94
|
})
|
|
95
95
|
}
|
|
@@ -146,9 +146,9 @@ export function ResetPasswordForm({ className, ...props }: React.ComponentProps<
|
|
|
146
146
|
/>
|
|
147
147
|
</Field>
|
|
148
148
|
<Field className="pt-4">
|
|
149
|
-
<Button type="submit" disabled={isPending}>
|
|
150
|
-
{isPending && <
|
|
151
|
-
{isPending ? 'Resetting
|
|
149
|
+
<Button type="submit" disabled={isPending} aria-busy={isPending}>
|
|
150
|
+
{isPending && <Spinner />}
|
|
151
|
+
{isPending ? 'Resetting…' : 'Reset Password'}
|
|
152
152
|
</Button>
|
|
153
153
|
</Field>
|
|
154
154
|
</div>
|
package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-table.tsx
CHANGED
|
@@ -238,7 +238,9 @@ export function AuditLogTable<TValue>({
|
|
|
238
238
|
className="flex h-24 items-center justify-center text-center"
|
|
239
239
|
style={{ gridColumn: '1 / -1' }}
|
|
240
240
|
>
|
|
241
|
-
<div className="text-destructive">
|
|
241
|
+
<div className="text-destructive">
|
|
242
|
+
Failed to load audit logs. Refresh to try again.
|
|
243
|
+
</div>
|
|
242
244
|
</DataGridCell>
|
|
243
245
|
</DataGridRow>
|
|
244
246
|
) : table.getRowModel().rows.length ? (
|
package/dist/assets/adapters/next/templates/init/pages/settings/forms/form-notifications-drawer.tsx
CHANGED
|
@@ -22,10 +22,10 @@ import {
|
|
|
22
22
|
FormMessage
|
|
23
23
|
} from '@admin/components/ui/form'
|
|
24
24
|
import { ScrollArea } from '@admin/components/ui/scroll-area'
|
|
25
|
+
import { Spinner } from '@admin/components/ui/spinner'
|
|
25
26
|
import { Textarea } from '@admin/components/ui/textarea'
|
|
26
27
|
import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'
|
|
27
28
|
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
|
28
|
-
import { LoaderCircle } from 'lucide-react'
|
|
29
29
|
import { useForm } from 'react-hook-form'
|
|
30
30
|
import { toast } from 'sonner'
|
|
31
31
|
import { z } from 'zod/v3'
|
|
@@ -75,7 +75,7 @@ export function FormNotificationsDrawer({
|
|
|
75
75
|
onOpenChange(false)
|
|
76
76
|
},
|
|
77
77
|
onError: (error: Error) => {
|
|
78
|
-
toast.error(error.message || '
|
|
78
|
+
toast.error(error.message || 'Failed to save these notification settings')
|
|
79
79
|
}
|
|
80
80
|
})
|
|
81
81
|
|
|
@@ -133,9 +133,14 @@ export function FormNotificationsDrawer({
|
|
|
133
133
|
Cancel
|
|
134
134
|
</Button>
|
|
135
135
|
</DrawerClose>
|
|
136
|
-
<Button
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
<Button
|
|
137
|
+
type="submit"
|
|
138
|
+
disabled={isPending || !form.formState.isDirty}
|
|
139
|
+
aria-busy={isPending}
|
|
140
|
+
size="lg"
|
|
141
|
+
>
|
|
142
|
+
{isPending && <Spinner />}
|
|
143
|
+
{isPending ? 'Saving…' : 'Save'}
|
|
139
144
|
</Button>
|
|
140
145
|
</DrawerFooter>
|
|
141
146
|
</form>
|
package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/delete-webhook-dialog.tsx
CHANGED
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
DialogHeader,
|
|
13
13
|
DialogTitle
|
|
14
14
|
} from '@admin/components/ui/dialog'
|
|
15
|
+
import { Spinner } from '@admin/components/ui/spinner'
|
|
15
16
|
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
|
16
|
-
import { LoaderCircle } from 'lucide-react'
|
|
17
17
|
import { toast } from 'sonner'
|
|
18
18
|
|
|
19
19
|
interface DeleteWebhookDialogProps {
|
|
@@ -27,16 +27,16 @@ export function DeleteWebhookDialog({ webhook, open, onOpenChange }: DeleteWebho
|
|
|
27
27
|
|
|
28
28
|
const mutation = useMutation({
|
|
29
29
|
mutationFn: async () => {
|
|
30
|
-
if (!webhook) throw new Error('No
|
|
30
|
+
if (!webhook) throw new Error('No webhook selected')
|
|
31
31
|
const result = await deleteWebhook(webhook.id)
|
|
32
32
|
if (!result.success) {
|
|
33
|
-
throw new Error(result.error || 'Failed to delete
|
|
33
|
+
throw new Error(result.error || 'Failed to delete this webhook')
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
return result
|
|
37
37
|
},
|
|
38
38
|
onSuccess: async () => {
|
|
39
|
-
toast.success('
|
|
39
|
+
toast.success('Webhook deleted')
|
|
40
40
|
await queryClient.invalidateQueries({ queryKey: ['webhooks'] })
|
|
41
41
|
await queryClient.invalidateQueries({
|
|
42
42
|
queryKey: ['webhook-subscriptions']
|
|
@@ -45,7 +45,7 @@ export function DeleteWebhookDialog({ webhook, open, onOpenChange }: DeleteWebho
|
|
|
45
45
|
onOpenChange(false)
|
|
46
46
|
},
|
|
47
47
|
onError: (error: Error) => {
|
|
48
|
-
toast.error(error.message || '
|
|
48
|
+
toast.error(error.message || 'Failed to delete this webhook')
|
|
49
49
|
}
|
|
50
50
|
})
|
|
51
51
|
|
|
@@ -55,25 +55,34 @@ export function DeleteWebhookDialog({ webhook, open, onOpenChange }: DeleteWebho
|
|
|
55
55
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
56
56
|
<DialogContent className="sm:max-w-105">
|
|
57
57
|
<DialogHeader>
|
|
58
|
-
<DialogTitle>Delete
|
|
58
|
+
<DialogTitle>Delete webhook?</DialogTitle>
|
|
59
59
|
<DialogDescription>
|
|
60
60
|
{webhook
|
|
61
|
-
? `"${webhook.name}"
|
|
62
|
-
: 'This
|
|
61
|
+
? `"${webhook.name}" stops receiving events. Its subscriptions and delivery history are deleted too.`
|
|
62
|
+
: 'This webhook stops receiving events.'}
|
|
63
63
|
</DialogDescription>
|
|
64
64
|
</DialogHeader>
|
|
65
65
|
<DialogBody>
|
|
66
66
|
<p className="text-sm text-muted-foreground">This action cannot be undone.</p>
|
|
67
67
|
</DialogBody>
|
|
68
68
|
<DialogFooter showCloseButton={true}>
|
|
69
|
+
<Button
|
|
70
|
+
variant="secondary"
|
|
71
|
+
size="lg"
|
|
72
|
+
disabled={isPending}
|
|
73
|
+
onClick={() => onOpenChange(false)}
|
|
74
|
+
>
|
|
75
|
+
Cancel
|
|
76
|
+
</Button>
|
|
69
77
|
<Button
|
|
70
78
|
variant="destructive"
|
|
71
79
|
size="lg"
|
|
72
80
|
disabled={isPending}
|
|
81
|
+
aria-busy={isPending}
|
|
73
82
|
onClick={() => mutation.mutate()}
|
|
74
83
|
>
|
|
75
|
-
{isPending && <
|
|
76
|
-
Delete
|
|
84
|
+
{isPending && <Spinner />}
|
|
85
|
+
{isPending ? 'Deleting…' : 'Delete webhook'}
|
|
77
86
|
</Button>
|
|
78
87
|
</DialogFooter>
|
|
79
88
|
</DialogContent>
|
package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhook-actions.tsx
CHANGED
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
DropdownMenuItem,
|
|
9
9
|
DropdownMenuTrigger
|
|
10
10
|
} from '@admin/components/ui/dropdown-menu'
|
|
11
|
+
import { Spinner } from '@admin/components/ui/spinner'
|
|
11
12
|
import { useSendTestWebhook } from '@admin/hooks/use-webhooks'
|
|
12
|
-
import {
|
|
13
|
+
import { MoreHorizontal } from 'lucide-react'
|
|
13
14
|
|
|
14
15
|
interface WebhookActionsProps {
|
|
15
16
|
webhook: WebhookEndpointListItem
|
|
@@ -30,7 +31,7 @@ export function WebhookActions({ webhook, onEdit, onDelete }: WebhookActionsProp
|
|
|
30
31
|
>
|
|
31
32
|
<span className="sr-only">Open webhook actions</span>
|
|
32
33
|
{sendTest.isPending ? (
|
|
33
|
-
<
|
|
34
|
+
<Spinner className="size-4" />
|
|
34
35
|
) : (
|
|
35
36
|
<MoreHorizontal className="size-4" />
|
|
36
37
|
)}
|
|
@@ -39,9 +40,13 @@ export function WebhookActions({ webhook, onEdit, onDelete }: WebhookActionsProp
|
|
|
39
40
|
<DropdownMenuContent align="end">
|
|
40
41
|
<DropdownMenuItem
|
|
41
42
|
disabled={sendTest.isPending}
|
|
42
|
-
|
|
43
|
+
aria-busy={sendTest.isPending}
|
|
44
|
+
onSelect={(event) => {
|
|
45
|
+
event.preventDefault()
|
|
46
|
+
sendTest.mutate(webhook.id)
|
|
47
|
+
}}
|
|
43
48
|
>
|
|
44
|
-
Test
|
|
49
|
+
{sendTest.isPending ? 'Testing…' : 'Test'}
|
|
45
50
|
</DropdownMenuItem>
|
|
46
51
|
<DropdownMenuItem onSelect={() => onEdit(webhook)}>Edit</DropdownMenuItem>
|
|
47
52
|
<DropdownMenuItem variant="destructive" onSelect={() => onDelete(webhook)}>
|