betterstart-cli 0.0.116 → 0.0.118
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/admin-globals.css +20 -0
- package/dist/assets/adapters/next/templates/init/components/shared/data-table/data-grid-row.tsx +33 -1
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-gallery-dialog.tsx +3 -3
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-preview.tsx +3 -1
- package/dist/assets/adapters/next/templates/init/hooks/use-copy-to-clipboard.ts +1 -3
- package/dist/assets/adapters/next/templates/init/hooks/use-field-error-visible.ts +25 -0
- package/dist/assets/adapters/next/templates/init/hooks/use-media.ts +1 -1
- package/dist/assets/adapters/next/templates/init/hooks/use-upload.ts +11 -5
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/cleanup-audit-logs.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/query-audit-logs.ts +2 -2
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/record-audit-event.ts +1 -2
- package/dist/assets/adapters/next/templates/init/lib/actions/auth/client.ts +4 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/entity-versions/get-entity-versions.ts +5 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/forms/get-all-form-settings.ts +1 -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 +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/media/update-media.ts +2 -4
- package/dist/assets/adapters/next/templates/init/lib/actions/profile/change-own-password.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/profile/update-email.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/upload/upload-files.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/upload/upload-media-from-url.ts +16 -6
- package/dist/assets/adapters/next/templates/init/lib/actions/users/change-user-password.ts +1 -0
- 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 +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/users/types.ts +1 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/update-user-role.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/db/core/schema.ts +12 -4
- package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/registry.ts +4 -4
- package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/runner.ts +3 -7
- package/dist/assets/adapters/next/templates/init/pages/container-layout.tsx +3 -0
- package/dist/assets/adapters/next/templates/init/pages/dashboard-page.tsx +78 -76
- package/dist/assets/adapters/next/templates/init/pages/forgot-password-form.tsx +5 -8
- package/dist/assets/adapters/next/templates/init/pages/forgot-password-page-skeleton.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/pages/login-form.tsx +7 -9
- package/dist/assets/adapters/next/templates/init/pages/login-page-skeleton.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/pages/reset-password-form.tsx +8 -16
- package/dist/assets/adapters/next/templates/init/pages/reset-password-page-skeleton.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-detail-row.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-table.tsx +1 -6
- package/dist/assets/adapters/next/templates/init/pages/settings/forms/forms-settings-table.tsx +2 -7
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhooks-table.tsx +1 -6
- package/dist/assets/adapters/next/templates/init/pages/users/users-table.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/public/placeholder.png +0 -0
- package/dist/assets/adapters/next/templates/init/types/index.ts +2 -0
- package/dist/assets/adapters/next/templates/init/utils/audit/normalize-comparable-value.ts +4 -2
- package/dist/assets/adapters/next/templates/init/utils/date/format-action-date.ts +12 -0
- package/dist/assets/adapters/next/templates/init/utils/dev-mode/dev-mode-json-schemas.ts +66 -0
- package/dist/assets/adapters/next/templates/init/utils/dev-mode/parse-dev-mode-lifecycle-hooks.ts +11 -0
- package/dist/assets/adapters/next/templates/init/utils/dev-mode/parse-dev-mode-snippets.ts +9 -0
- package/dist/assets/adapters/next/templates/init/utils/editor/set-task-item-checked.ts +13 -0
- package/dist/assets/adapters/next/templates/init/utils/editor/update-nodes-attr.ts +2 -1
- package/dist/assets/adapters/next/templates/init/utils/email/email-theme.ts +13 -0
- package/dist/assets/adapters/next/templates/init/utils/email/render-form-submission-rows.ts +3 -2
- package/dist/assets/adapters/next/templates/init/utils/email/render-notification-email.ts +7 -6
- package/dist/assets/adapters/next/templates/init/utils/email/render-thank-you-email.ts +5 -4
- package/dist/assets/adapters/next/templates/init/utils/error/read-string-property.ts +4 -2
- package/dist/assets/adapters/next/templates/init/utils/error/recognize.ts +2 -4
- package/dist/assets/adapters/next/templates/init/utils/error/to-action-error.ts +0 -1
- package/dist/assets/adapters/next/templates/init/utils/form/clone-default-value.ts +4 -2
- package/dist/assets/adapters/next/templates/init/utils/shared/is-record.ts +3 -0
- package/dist/assets/adapters/next/templates/init/utils/table/default-get-id.ts +3 -2
- package/dist/assets/shared-assets/react-admin/custom/content-editor/editor-toolbar.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/slash-command-menu.tsx +5 -3
- package/dist/assets/shared-assets/react-admin/custom/content-editor/source-mode.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-node/removable-image-node/removable-image-node.tsx +3 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-node/task-item-node/task-item-node-extension.tsx +6 -15
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu.tsx +1 -6
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/list-dropdown-menu/list-dropdown-menu.tsx +1 -6
- package/dist/assets/shared-assets/react-admin/custom/date-range-picker.tsx +9 -2
- package/dist/assets/shared-assets/react-admin/custom/gallery-field.tsx +3 -3
- package/dist/assets/shared-assets/react-admin/custom/media-field.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/custom/nested-object-list-field.tsx +3 -1
- package/dist/assets/shared-assets/react-admin/custom/progressive-blur.tsx +3 -1
- package/dist/assets/shared-assets/react-admin/ui/dropdown-menu.tsx +20 -23
- package/dist/assets/shared-assets/react-admin/ui/form.tsx +6 -3
- package/dist/assets/shared-assets/react-admin/ui/navigation-menu.tsx +1 -1
- package/dist/{chunk-SG4U6EQY.js → chunk-BNHFSHPE.js} +14 -1
- package/dist/chunk-BNHFSHPE.js.map +1 -0
- package/dist/cli.js +962 -633
- package/dist/cli.js.map +1 -1
- package/dist/{read-namespaced-template-D2CD4Q7U.js → read-namespaced-template-WYIGUH7S.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-SG4U6EQY.js.map +0 -1
- /package/dist/{read-namespaced-template-D2CD4Q7U.js.map → read-namespaced-template-WYIGUH7S.js.map} +0 -0
|
@@ -35,86 +35,88 @@ export default function DashboardPage() {
|
|
|
35
35
|
<PageHeader title="Dashboard" hasBackButton={false} />
|
|
36
36
|
|
|
37
37
|
<div className="w-full space-y-6 p-6">
|
|
38
|
-
<
|
|
39
|
-
<
|
|
40
|
-
<
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
</CardHeader>
|
|
45
|
-
<CardContent className="p-10!">
|
|
46
|
-
<div className="grid grid-cols-2 gap-10">
|
|
47
|
-
<div className="flex w-full flex-col gap-1">
|
|
48
|
-
<p className="text-base font-medium">Hey, let's get started</p>
|
|
49
|
-
<p className="text-muted-foreground">
|
|
50
|
-
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos.
|
|
51
|
-
</p>
|
|
38
|
+
<div className="container mx-auto">
|
|
39
|
+
<Card>
|
|
40
|
+
<CardHeader>
|
|
41
|
+
<div className="flex items-center gap-2">
|
|
42
|
+
<CircleGauge className="size-4 text-muted-foreground" />
|
|
43
|
+
<CardTitle className="font-medium">Setup your dashboard</CardTitle>
|
|
52
44
|
</div>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
>
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
45
|
+
</CardHeader>
|
|
46
|
+
<CardContent className="p-10!">
|
|
47
|
+
<div className="grid grid-cols-2 gap-10">
|
|
48
|
+
<div className="flex w-full flex-col gap-1">
|
|
49
|
+
<p className="text-base font-medium">Hey, let's get started</p>
|
|
50
|
+
<p className="text-muted-foreground">
|
|
51
|
+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos.
|
|
52
|
+
</p>
|
|
53
|
+
</div>
|
|
54
|
+
<div className="flex w-full flex-col">
|
|
55
|
+
<Accordion defaultValue={['item-1']}>
|
|
56
|
+
<AccordionItem value="item-1">
|
|
57
|
+
<AccordionTrigger>
|
|
58
|
+
<div className="flex items-center gap-3">
|
|
59
|
+
<ShieldEllipsis className="size-4 text-muted-foreground" />
|
|
60
|
+
<span>Setup ENV Variables</span>
|
|
61
|
+
</div>
|
|
62
|
+
</AccordionTrigger>
|
|
63
|
+
<AccordionContent className="h-auto pl-7">
|
|
64
|
+
<div className="flex w-full flex-col gap-1">
|
|
65
|
+
{envVariables.map((env) => (
|
|
66
|
+
<div
|
|
67
|
+
className="flex w-full flex-col rounded-sm border border-border bg-card py-2 pr-2 pl-4 shadow-card"
|
|
68
|
+
key={env.name}
|
|
69
|
+
>
|
|
70
|
+
<div className="flex items-center justify-between">
|
|
71
|
+
<div className="flex items-center gap-2">
|
|
72
|
+
<span className="">{env.label}</span>
|
|
73
|
+
<Badge variant={env.value ? 'success' : 'destructive'}>
|
|
74
|
+
{env.value ? 'Connected' : 'Not configured'}
|
|
75
|
+
</Badge>
|
|
76
|
+
</div>
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
<Button variant="ghost" className="size-8">
|
|
79
|
+
<FileQuestion className="size-4" />
|
|
80
|
+
</Button>
|
|
81
|
+
</div>
|
|
80
82
|
</div>
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
</
|
|
84
|
-
</
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
</
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
</
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
</
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
</
|
|
113
|
-
</
|
|
83
|
+
))}
|
|
84
|
+
</div>
|
|
85
|
+
</AccordionContent>
|
|
86
|
+
</AccordionItem>
|
|
87
|
+
<AccordionItem value="item-2">
|
|
88
|
+
<AccordionTrigger>
|
|
89
|
+
<div className="flex items-center gap-3">
|
|
90
|
+
<Blocks className="size-4 text-muted-foreground" />
|
|
91
|
+
<span>Install Pre-built Modules</span>
|
|
92
|
+
</div>
|
|
93
|
+
</AccordionTrigger>
|
|
94
|
+
<AccordionContent className="pl-7">Lorem</AccordionContent>
|
|
95
|
+
</AccordionItem>
|
|
96
|
+
<AccordionItem value="item-3">
|
|
97
|
+
<AccordionTrigger>
|
|
98
|
+
<div className="flex items-center gap-3">
|
|
99
|
+
<PlugZap className="size-4 text-muted-foreground" />
|
|
100
|
+
<span>Setup Provider Integrations</span>
|
|
101
|
+
</div>
|
|
102
|
+
</AccordionTrigger>
|
|
103
|
+
<AccordionContent className="pl-7">Lorem</AccordionContent>
|
|
104
|
+
</AccordionItem>
|
|
105
|
+
<AccordionItem value="item-4">
|
|
106
|
+
<AccordionTrigger>
|
|
107
|
+
<div className="flex items-center gap-3">
|
|
108
|
+
<Globe className="size-4 text-muted-foreground" />
|
|
109
|
+
<span>Deploy</span>
|
|
110
|
+
</div>
|
|
111
|
+
</AccordionTrigger>
|
|
112
|
+
<AccordionContent className="pl-7">Lorem</AccordionContent>
|
|
113
|
+
</AccordionItem>
|
|
114
|
+
</Accordion>
|
|
115
|
+
</div>
|
|
114
116
|
</div>
|
|
115
|
-
</
|
|
116
|
-
</
|
|
117
|
-
</
|
|
117
|
+
</CardContent>
|
|
118
|
+
</Card>
|
|
119
|
+
</div>
|
|
118
120
|
</div>
|
|
119
121
|
</React.Fragment>
|
|
120
122
|
)
|
|
@@ -10,6 +10,7 @@ import { Field, FieldGroup, FieldLabel } from '@admin/components/ui/field'
|
|
|
10
10
|
import { Form } from '@admin/components/ui/form'
|
|
11
11
|
import { Input } from '@admin/components/ui/input'
|
|
12
12
|
import { Spinner } from '@admin/components/ui/spinner'
|
|
13
|
+
import { useFieldErrorVisible } from '@admin/hooks/use-field-error-visible'
|
|
13
14
|
import { cn } from '@admin/utils/shared/cn'
|
|
14
15
|
import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'
|
|
15
16
|
import Image from 'next/image'
|
|
@@ -33,6 +34,8 @@ export function ForgotPasswordForm({ className, ...props }: React.ComponentProps
|
|
|
33
34
|
reValidateMode: 'onChange'
|
|
34
35
|
})
|
|
35
36
|
|
|
37
|
+
const isEmailErrorVisible = useFieldErrorVisible(form, 'email')
|
|
38
|
+
|
|
36
39
|
const handleSubmit = (values: ForgotPasswordFormValues) => {
|
|
37
40
|
startTransition(async () => {
|
|
38
41
|
try {
|
|
@@ -68,13 +71,7 @@ export function ForgotPasswordForm({ className, ...props }: React.ComponentProps
|
|
|
68
71
|
<Card className="overflow-hidden p-0">
|
|
69
72
|
<CardContent className="grid grid-cols-[5fr_7fr] p-0">
|
|
70
73
|
<div className="relative block bg-muted">
|
|
71
|
-
<Image
|
|
72
|
-
src="https://assets.betterstart.dev/assets/placeholder.png"
|
|
73
|
-
alt=""
|
|
74
|
-
fill
|
|
75
|
-
sizes="42vw"
|
|
76
|
-
className="object-cover"
|
|
77
|
-
/>
|
|
74
|
+
<Image src="/placeholder.png" alt="" fill sizes="42vw" className="object-cover" />
|
|
78
75
|
</div>
|
|
79
76
|
<div className="p-20">
|
|
80
77
|
<Form {...form}>
|
|
@@ -99,7 +96,7 @@ export function ForgotPasswordForm({ className, ...props }: React.ComponentProps
|
|
|
99
96
|
type="email"
|
|
100
97
|
autoComplete="off"
|
|
101
98
|
placeholder="m@example.com"
|
|
102
|
-
aria-invalid={
|
|
99
|
+
aria-invalid={isEmailErrorVisible}
|
|
103
100
|
{...form.register('email')}
|
|
104
101
|
required
|
|
105
102
|
disabled={isPending}
|
|
@@ -2,8 +2,8 @@ export function ForgotPasswordPageSkeleton() {
|
|
|
2
2
|
return (
|
|
3
3
|
<div className="overflow-hidden rounded-sm border bg-card">
|
|
4
4
|
<div className="grid grid-cols-[5fr_7fr]">
|
|
5
|
-
<div className="block min-h-
|
|
6
|
-
<div className="flex min-h-
|
|
5
|
+
<div className="block min-h-auth-forgot-panel bg-muted" />
|
|
6
|
+
<div className="flex min-h-auth-forgot-panel flex-col gap-10 p-20">
|
|
7
7
|
<div className="space-y-3">
|
|
8
8
|
<div className="h-6 w-40 animate-pulse rounded-md bg-muted" />
|
|
9
9
|
<div className="h-4 w-full max-w-72 animate-pulse rounded-md bg-muted" />
|
|
@@ -9,6 +9,7 @@ import { Field, FieldGroup, FieldLabel } from '@admin/components/ui/field'
|
|
|
9
9
|
import { Form } from '@admin/components/ui/form'
|
|
10
10
|
import { Input } from '@admin/components/ui/input'
|
|
11
11
|
import { Spinner } from '@admin/components/ui/spinner'
|
|
12
|
+
import { useFieldErrorVisible } from '@admin/hooks/use-field-error-visible'
|
|
12
13
|
import { getAdminPostLoginPath } from '@admin/utils/auth/get-admin-post-login-path'
|
|
13
14
|
import { cn } from '@admin/utils/shared/cn'
|
|
14
15
|
import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'
|
|
@@ -41,6 +42,9 @@ export function LoginForm({ className, ...props }: React.ComponentProps<'div'>)
|
|
|
41
42
|
reValidateMode: 'onChange'
|
|
42
43
|
})
|
|
43
44
|
|
|
45
|
+
const isEmailErrorVisible = useFieldErrorVisible(form, 'email')
|
|
46
|
+
const isPasswordErrorVisible = useFieldErrorVisible(form, 'password')
|
|
47
|
+
|
|
44
48
|
React.useEffect(() => {
|
|
45
49
|
if (reset === 'success') {
|
|
46
50
|
toast.success('Password reset. Sign in with your new password.', {
|
|
@@ -83,13 +87,7 @@ export function LoginForm({ className, ...props }: React.ComponentProps<'div'>)
|
|
|
83
87
|
<Card className="overflow-hidden p-0">
|
|
84
88
|
<CardContent className="grid grid-cols-[5fr_7fr] p-0">
|
|
85
89
|
<div className="relative block bg-muted">
|
|
86
|
-
<Image
|
|
87
|
-
src="https://assets.betterstart.dev/assets/placeholder.png"
|
|
88
|
-
alt=""
|
|
89
|
-
fill
|
|
90
|
-
sizes="42vw"
|
|
91
|
-
className="object-cover"
|
|
92
|
-
/>
|
|
90
|
+
<Image src="/placeholder.png" alt="" fill sizes="42vw" className="object-cover" />
|
|
93
91
|
</div>
|
|
94
92
|
<Form {...form}>
|
|
95
93
|
<form
|
|
@@ -110,7 +108,7 @@ export function LoginForm({ className, ...props }: React.ComponentProps<'div'>)
|
|
|
110
108
|
type="email"
|
|
111
109
|
autoComplete="off"
|
|
112
110
|
placeholder="m@example.com"
|
|
113
|
-
aria-invalid={
|
|
111
|
+
aria-invalid={isEmailErrorVisible}
|
|
114
112
|
{...form.register('email')}
|
|
115
113
|
required
|
|
116
114
|
disabled={isPending}
|
|
@@ -132,7 +130,7 @@ export function LoginForm({ className, ...props }: React.ComponentProps<'div'>)
|
|
|
132
130
|
type="password"
|
|
133
131
|
autoComplete="off"
|
|
134
132
|
placeholder="Enter your password"
|
|
135
|
-
aria-invalid={
|
|
133
|
+
aria-invalid={isPasswordErrorVisible}
|
|
136
134
|
{...form.register('password')}
|
|
137
135
|
required
|
|
138
136
|
disabled={isPending}
|
|
@@ -2,8 +2,8 @@ export function LoginPageSkeleton() {
|
|
|
2
2
|
return (
|
|
3
3
|
<div className="overflow-hidden rounded-sm border bg-card">
|
|
4
4
|
<div className="grid grid-cols-[5fr_7fr]">
|
|
5
|
-
<div className="block min-h-
|
|
6
|
-
<div className="flex min-h-
|
|
5
|
+
<div className="block min-h-auth-login-panel bg-muted" />
|
|
6
|
+
<div className="flex min-h-auth-login-panel flex-col gap-10 p-20">
|
|
7
7
|
<div className="space-y-3">
|
|
8
8
|
<div className="h-6 w-32 animate-pulse rounded-md bg-muted" />
|
|
9
9
|
<div className="h-4 w-40 animate-pulse rounded-md bg-muted" />
|
|
@@ -9,6 +9,7 @@ import { Field, FieldGroup, FieldLabel } from '@admin/components/ui/field'
|
|
|
9
9
|
import { Form } from '@admin/components/ui/form'
|
|
10
10
|
import { Input } from '@admin/components/ui/input'
|
|
11
11
|
import { Spinner } from '@admin/components/ui/spinner'
|
|
12
|
+
import { useFieldErrorVisible } from '@admin/hooks/use-field-error-visible'
|
|
12
13
|
import { cn } from '@admin/utils/shared/cn'
|
|
13
14
|
import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'
|
|
14
15
|
import Image from 'next/image'
|
|
@@ -49,19 +50,16 @@ export function ResetPasswordForm({ className, ...props }: React.ComponentProps<
|
|
|
49
50
|
reValidateMode: 'onChange'
|
|
50
51
|
})
|
|
51
52
|
|
|
53
|
+
const isNewPasswordErrorVisible = useFieldErrorVisible(form, 'newPassword')
|
|
54
|
+
const isConfirmPasswordErrorVisible = useFieldErrorVisible(form, 'confirmPassword')
|
|
55
|
+
|
|
52
56
|
if (!token) {
|
|
53
57
|
return (
|
|
54
58
|
<div className={cn('flex flex-col gap-6', className)} {...props}>
|
|
55
59
|
<Card className="overflow-hidden p-0">
|
|
56
60
|
<CardContent className="grid grid-cols-[5fr_7fr] p-0">
|
|
57
61
|
<div className="relative block bg-muted">
|
|
58
|
-
<Image
|
|
59
|
-
src="https://assets.betterstart.dev/assets/placeholder.png"
|
|
60
|
-
alt=""
|
|
61
|
-
fill
|
|
62
|
-
sizes="42vw"
|
|
63
|
-
className="object-cover"
|
|
64
|
-
/>
|
|
62
|
+
<Image src="/placeholder.png" alt="" fill sizes="42vw" className="object-cover" />
|
|
65
63
|
</div>
|
|
66
64
|
<div className="p-20">
|
|
67
65
|
<FieldGroup className="gap-10 pb-12">
|
|
@@ -114,13 +112,7 @@ export function ResetPasswordForm({ className, ...props }: React.ComponentProps<
|
|
|
114
112
|
<Card className="overflow-hidden p-0">
|
|
115
113
|
<CardContent className="grid grid-cols-[5fr_7fr] p-0">
|
|
116
114
|
<div className="relative block bg-muted">
|
|
117
|
-
<Image
|
|
118
|
-
src="https://assets.betterstart.dev/assets/placeholder.png"
|
|
119
|
-
alt=""
|
|
120
|
-
fill
|
|
121
|
-
sizes="42vw"
|
|
122
|
-
className="object-cover"
|
|
123
|
-
/>
|
|
115
|
+
<Image src="/placeholder.png" alt="" fill sizes="42vw" className="object-cover" />
|
|
124
116
|
</div>
|
|
125
117
|
<Form {...form}>
|
|
126
118
|
<form
|
|
@@ -144,7 +136,7 @@ export function ResetPasswordForm({ className, ...props }: React.ComponentProps<
|
|
|
144
136
|
type="password"
|
|
145
137
|
autoComplete="off"
|
|
146
138
|
placeholder="Enter new password"
|
|
147
|
-
aria-invalid={
|
|
139
|
+
aria-invalid={isNewPasswordErrorVisible}
|
|
148
140
|
{...form.register('newPassword')}
|
|
149
141
|
required
|
|
150
142
|
disabled={isPending}
|
|
@@ -157,7 +149,7 @@ export function ResetPasswordForm({ className, ...props }: React.ComponentProps<
|
|
|
157
149
|
type="password"
|
|
158
150
|
autoComplete="off"
|
|
159
151
|
placeholder="Confirm new password"
|
|
160
|
-
aria-invalid={
|
|
152
|
+
aria-invalid={isConfirmPasswordErrorVisible}
|
|
161
153
|
{...form.register('confirmPassword')}
|
|
162
154
|
required
|
|
163
155
|
disabled={isPending}
|
|
@@ -2,8 +2,8 @@ export function ResetPasswordPageSkeleton() {
|
|
|
2
2
|
return (
|
|
3
3
|
<div className="overflow-hidden rounded-sm border bg-card">
|
|
4
4
|
<div className="grid grid-cols-[5fr_7fr]">
|
|
5
|
-
<div className="block min-h-
|
|
6
|
-
<div className="flex min-h-
|
|
5
|
+
<div className="block min-h-auth-reset-panel bg-muted" />
|
|
6
|
+
<div className="flex min-h-auth-reset-panel flex-col gap-10 p-20">
|
|
7
7
|
<div className="space-y-3">
|
|
8
8
|
<div className="h-6 w-36 animate-pulse rounded-md bg-muted" />
|
|
9
9
|
<div className="h-4 w-56 animate-pulse rounded-md bg-muted" />
|
package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-detail-row.tsx
CHANGED
|
@@ -7,7 +7,7 @@ interface AuditLogDetailRowProps {
|
|
|
7
7
|
|
|
8
8
|
export function AuditLogDetailRow({ label, value }: AuditLogDetailRowProps) {
|
|
9
9
|
return (
|
|
10
|
-
<div className="grid grid-cols-
|
|
10
|
+
<div className="grid grid-cols-audit-detail gap-3 border-b border-border px-4 py-2 last:border-b-0">
|
|
11
11
|
<dt className="text-sm font-medium text-muted-foreground">{label}</dt>
|
|
12
12
|
<dd className="min-w-0 text-sm break-words text-foreground">{value || 'Unknown'}</dd>
|
|
13
13
|
</div>
|
package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-table.tsx
CHANGED
|
@@ -248,12 +248,7 @@ export function AuditLogTable<TValue>({
|
|
|
248
248
|
<DataGridRow
|
|
249
249
|
key={row.id}
|
|
250
250
|
className="cursor-pointer hover:bg-muted/50"
|
|
251
|
-
|
|
252
|
-
const target = event.target as HTMLElement
|
|
253
|
-
if (!event.currentTarget.contains(target)) return
|
|
254
|
-
if (target.closest('button, a, input, [role="checkbox"]')) return
|
|
255
|
-
onRowClick(row.original)
|
|
256
|
-
}}
|
|
251
|
+
onActivate={() => onRowClick(row.original)}
|
|
257
252
|
>
|
|
258
253
|
{row.getVisibleCells().map((cell) => (
|
|
259
254
|
<DataGridCell
|
package/dist/assets/adapters/next/templates/init/pages/settings/forms/forms-settings-table.tsx
CHANGED
|
@@ -36,7 +36,7 @@ export function FormsSettingsTable({
|
|
|
36
36
|
<div className={cn('flex h-full flex-col gap-6 pt-px pb-2', className)}>
|
|
37
37
|
<DataGrid
|
|
38
38
|
containerClassName="min-h-0 flex-1"
|
|
39
|
-
gridTemplateColumns="minmax(
|
|
39
|
+
gridTemplateColumns="minmax(var(--spacing-form-settings-name), 1fr) minmax(var(--spacing-form-settings-recipients), 2fr)"
|
|
40
40
|
>
|
|
41
41
|
<DataGridHeader>
|
|
42
42
|
{table.getHeaderGroups().map((headerGroup) => (
|
|
@@ -57,12 +57,7 @@ export function FormsSettingsTable({
|
|
|
57
57
|
<DataGridRow
|
|
58
58
|
key={row.id}
|
|
59
59
|
className="cursor-pointer hover:bg-muted/50"
|
|
60
|
-
|
|
61
|
-
const target = event.target as HTMLElement
|
|
62
|
-
if (!event.currentTarget.contains(target)) return
|
|
63
|
-
if (target.closest('button, a, input, [role="checkbox"]')) return
|
|
64
|
-
onRowClick(row.original)
|
|
65
|
-
}}
|
|
60
|
+
onActivate={() => onRowClick(row.original)}
|
|
66
61
|
>
|
|
67
62
|
{row.getVisibleCells().map((cell) => (
|
|
68
63
|
<DataGridCell key={cell.id} data-column-id={cell.column.id}>
|
|
@@ -217,12 +217,7 @@ export function WebhooksTable<TValue>({
|
|
|
217
217
|
<DataGridRow
|
|
218
218
|
key={row.id}
|
|
219
219
|
className="cursor-pointer hover:bg-muted/50"
|
|
220
|
-
|
|
221
|
-
const target = e.target as HTMLElement
|
|
222
|
-
if (!e.currentTarget.contains(target)) return
|
|
223
|
-
if (target.closest('button, a, input, [role="checkbox"], [role="switch"]')) return
|
|
224
|
-
onRowClick(row.original)
|
|
225
|
-
}}
|
|
220
|
+
onActivate={() => onRowClick(row.original)}
|
|
226
221
|
>
|
|
227
222
|
{row.getVisibleCells().map((cell) => (
|
|
228
223
|
<DataGridCell
|
|
@@ -118,7 +118,7 @@ export function UsersTable<TValue>({
|
|
|
118
118
|
email: session.user.email,
|
|
119
119
|
name: session.user.name,
|
|
120
120
|
image: session.user.image,
|
|
121
|
-
role:
|
|
121
|
+
role: session.user.role || 'member'
|
|
122
122
|
}
|
|
123
123
|
: null
|
|
124
124
|
},
|
|
Binary file
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { isRecord } from '@admin/utils/shared/is-record'
|
|
2
|
+
|
|
1
3
|
export function normalizeComparableValue(value: unknown): string {
|
|
2
4
|
if (value instanceof Date) return value.toISOString()
|
|
3
5
|
if (Array.isArray(value)) {
|
|
4
6
|
return JSON.stringify(value.map((item) => normalizeComparableValue(item)))
|
|
5
7
|
}
|
|
6
|
-
if (value
|
|
7
|
-
const entries = Object.entries(value
|
|
8
|
+
if (isRecord(value)) {
|
|
9
|
+
const entries = Object.entries(value)
|
|
8
10
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
9
11
|
.map(([key, item]) => [key, normalizeComparableValue(item)])
|
|
10
12
|
return JSON.stringify(entries)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function formatActionDate(value: unknown): string {
|
|
2
|
+
if (typeof value !== 'string') return ''
|
|
3
|
+
const date = new Date(value)
|
|
4
|
+
if (Number.isNaN(date.getTime())) return ''
|
|
5
|
+
|
|
6
|
+
return date.toLocaleDateString('en-US', {
|
|
7
|
+
month: 'short',
|
|
8
|
+
day: '2-digit',
|
|
9
|
+
year: 'numeric',
|
|
10
|
+
timeZone: 'UTC'
|
|
11
|
+
})
|
|
12
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { z } from 'zod/v3'
|
|
2
|
+
|
|
3
|
+
export const devModeCodeLanguageSchema = z.enum(['tsx', 'ts', 'json'])
|
|
4
|
+
|
|
5
|
+
export const devModeSnippetIconSchema = z.enum([
|
|
6
|
+
'eye',
|
|
7
|
+
'file-code',
|
|
8
|
+
'inbox',
|
|
9
|
+
'list',
|
|
10
|
+
'pencil',
|
|
11
|
+
'plus',
|
|
12
|
+
'save',
|
|
13
|
+
'send',
|
|
14
|
+
'trash'
|
|
15
|
+
])
|
|
16
|
+
|
|
17
|
+
export const devModeSnippetExampleSchema = z.object({
|
|
18
|
+
label: z.string(),
|
|
19
|
+
language: devModeCodeLanguageSchema,
|
|
20
|
+
code: z.string()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
export const devModeSnippetCodeTabSchema = z.object({
|
|
24
|
+
id: z.string(),
|
|
25
|
+
label: z.string(),
|
|
26
|
+
language: devModeCodeLanguageSchema,
|
|
27
|
+
code: z.string()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
export const devModeSnippetSchema = z.object({
|
|
31
|
+
id: z.string(),
|
|
32
|
+
label: z.string(),
|
|
33
|
+
kind: z.enum(['jsx', 'query', 'mutation']),
|
|
34
|
+
icon: devModeSnippetIconSchema,
|
|
35
|
+
language: devModeCodeLanguageSchema,
|
|
36
|
+
code: z.string(),
|
|
37
|
+
codeTabs: z.array(devModeSnippetCodeTabSchema).optional(),
|
|
38
|
+
payloadExample: devModeSnippetExampleSchema.optional(),
|
|
39
|
+
responseExample: devModeSnippetExampleSchema.optional()
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
export const devModeLifecycleHookExampleSchema = z.object({
|
|
43
|
+
id: z.string(),
|
|
44
|
+
label: z.string(),
|
|
45
|
+
event: z.enum([
|
|
46
|
+
'beforeCreate',
|
|
47
|
+
'afterCreate',
|
|
48
|
+
'beforeUpdate',
|
|
49
|
+
'afterUpdate',
|
|
50
|
+
'beforeDelete',
|
|
51
|
+
'afterDelete',
|
|
52
|
+
'beforePublish',
|
|
53
|
+
'afterPublish',
|
|
54
|
+
'beforeUnpublish',
|
|
55
|
+
'afterUnpublish',
|
|
56
|
+
'beforeRestore',
|
|
57
|
+
'afterRestore',
|
|
58
|
+
'beforeReorder',
|
|
59
|
+
'afterReorder'
|
|
60
|
+
]),
|
|
61
|
+
phase: z.enum(['before', 'after']),
|
|
62
|
+
icon: devModeSnippetIconSchema,
|
|
63
|
+
language: devModeCodeLanguageSchema,
|
|
64
|
+
code: z.string(),
|
|
65
|
+
contextExample: devModeSnippetExampleSchema
|
|
66
|
+
})
|
package/dist/assets/adapters/next/templates/init/utils/dev-mode/parse-dev-mode-lifecycle-hooks.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DevModeLifecycleHookExample } from '@admin/components/shared/dev-mode/dev-mode-types'
|
|
2
|
+
import { devModeLifecycleHookExampleSchema } from '@admin/utils/dev-mode/dev-mode-json-schemas'
|
|
3
|
+
import { z } from 'zod/v3'
|
|
4
|
+
|
|
5
|
+
const lifecycleHooksSchema = z.array(devModeLifecycleHookExampleSchema)
|
|
6
|
+
|
|
7
|
+
export function parseDevModeLifecycleHooks<Raw>(
|
|
8
|
+
values: readonly Raw[]
|
|
9
|
+
): DevModeLifecycleHookExample[] {
|
|
10
|
+
return lifecycleHooksSchema.parse(values)
|
|
11
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DevModeSnippet } from '@admin/components/shared/dev-mode/dev-mode-types'
|
|
2
|
+
import { devModeSnippetSchema } from '@admin/utils/dev-mode/dev-mode-json-schemas'
|
|
3
|
+
import { z } from 'zod/v3'
|
|
4
|
+
|
|
5
|
+
const snippetsSchema = z.array(devModeSnippetSchema)
|
|
6
|
+
|
|
7
|
+
export function parseDevModeSnippets<Raw>(values: readonly Raw[]): DevModeSnippet[] {
|
|
8
|
+
return snippetsSchema.parse(values)
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Transaction } from '@tiptap/pm/state'
|
|
2
|
+
|
|
3
|
+
export function setTaskItemChecked(
|
|
4
|
+
tr: Transaction,
|
|
5
|
+
position: number | undefined,
|
|
6
|
+
checked: boolean
|
|
7
|
+
): boolean {
|
|
8
|
+
if (typeof position !== 'number') return false
|
|
9
|
+
|
|
10
|
+
const taskItem = tr.doc.nodeAt(position)
|
|
11
|
+
tr.setNodeMarkup(position, undefined, { ...taskItem?.attrs, checked })
|
|
12
|
+
return true
|
|
13
|
+
}
|
|
@@ -15,7 +15,8 @@ export function updateNodesAttr<A extends string = string, V = unknown>(
|
|
|
15
15
|
const currentNode = tr.doc.nodeAt(pos)
|
|
16
16
|
if (!currentNode) continue
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const attrs: Record<string, unknown> = currentNode.attrs
|
|
19
|
+
const prevValue = attrs[attrName] as V | undefined
|
|
19
20
|
const resolvedNext =
|
|
20
21
|
typeof next === 'function' ? (next as (p: V | undefined) => V | undefined)(prevValue) : next
|
|
21
22
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const emailTheme = {
|
|
2
|
+
pageBackground: '#f8fafc',
|
|
3
|
+
surface: '#ffffff',
|
|
4
|
+
border: '#e2e8f0',
|
|
5
|
+
headerBackground: '#0f172a',
|
|
6
|
+
text: '#0f172a',
|
|
7
|
+
bodyText: '#334155',
|
|
8
|
+
mutedText: '#475569',
|
|
9
|
+
inverseText: '#ffffff',
|
|
10
|
+
mutedInverseText: '#cbd5e1',
|
|
11
|
+
compactWidth: '560px',
|
|
12
|
+
contentWidth: '640px'
|
|
13
|
+
} as const
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { emailTheme } from '@admin/utils/email/email-theme'
|
|
1
2
|
import { escapeHtml } from '@admin/utils/email/escape-html'
|
|
2
3
|
import { formatEmailValue } from '@admin/utils/email/format-email-value'
|
|
3
4
|
|
|
@@ -8,8 +9,8 @@ export function renderFormSubmissionRows(submissionData: Record<string, unknown>
|
|
|
8
9
|
const displayValue = escapeHtml(formatEmailValue(value))
|
|
9
10
|
|
|
10
11
|
return `<tr>
|
|
11
|
-
<th style="border-bottom:1px solid
|
|
12
|
-
<td style="border-bottom:1px solid
|
|
12
|
+
<th style="border-bottom:1px solid ${emailTheme.border};color:${emailTheme.mutedText};font-size:12px;font-weight:600;padding:12px;text-align:left;text-transform:uppercase;vertical-align:top;width:36%;">${label}</th>
|
|
13
|
+
<td style="border-bottom:1px solid ${emailTheme.border};color:${emailTheme.text};font-size:14px;line-height:20px;padding:12px;vertical-align:top;">${displayValue}</td>
|
|
13
14
|
</tr>`
|
|
14
15
|
})
|
|
15
16
|
.join('\n')
|