betterstart-cli 0.0.16 → 0.0.18
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/plugins/blog/schemas/menus.json +1 -0
- package/dist/assets/adapters/next/plugins/blog/schemas/posts.json +132 -99
- package/dist/assets/adapters/next/plugins/portfolio/plugin.ts +17 -0
- package/dist/assets/adapters/next/plugins/portfolio/schemas/portfolio.json +128 -0
- package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/dev-mode-types.ts +2 -2
- package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/snippets-tab.tsx +1 -0
- package/dist/assets/adapters/next/templates/init/components/shared/dev-mode-integrate.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-delete-dialog.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-delete-drawer.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-grid-item.tsx +17 -7
- package/dist/assets/adapters/next/templates/init/data/navigation.ts +2 -1
- package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-content-editor-source-mode.tsx +3 -3
- package/dist/assets/adapters/next/templates/init/hooks/use-media.ts +2 -1
- package/dist/assets/adapters/next/templates/init/pages/profile/profile-form.tsx +3 -3
- package/dist/assets/adapters/next/templates/init/types/index.ts +7 -2
- package/dist/assets/shared-assets/react-admin/custom/content-editor/media-gallery-block.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/custom/content-editor/table-add-controls.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/custom/gallery-field.tsx +219 -40
- package/dist/assets/shared-assets/react-admin/custom/media-field-empty-state.tsx +99 -0
- package/dist/assets/shared-assets/react-admin/custom/media-field.tsx +181 -0
- package/dist/assets/shared-assets/react-admin/custom/sortable-gallery-item.tsx +38 -38
- package/dist/assets/shared-assets/react-admin/dependencies.ts +1 -0
- package/dist/assets/shared-assets/react-admin/schema.json +64 -2
- package/dist/assets/shared-assets/react-admin/ui/chart.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/pagination.tsx +1 -1
- package/dist/cli.js +562 -151
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/dist/assets/shared-assets/react-admin/custom/gallery-thumbnail.tsx +0 -39
- package/dist/assets/shared-assets/react-admin/custom/media-gallery-field.tsx +0 -182
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "posts",
|
|
3
|
+
"type": "entity",
|
|
3
4
|
"label": "Posts",
|
|
4
5
|
"description": "Manage blog posts",
|
|
5
6
|
"icon": "FileText",
|
|
@@ -12,110 +13,142 @@
|
|
|
12
13
|
"main": {
|
|
13
14
|
"fields": [
|
|
14
15
|
{
|
|
15
|
-
"name": "
|
|
16
|
-
"type": "
|
|
17
|
-
"
|
|
18
|
-
"required": true
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"name": "slug",
|
|
22
|
-
"type": "string",
|
|
23
|
-
"label": "Slug",
|
|
24
|
-
"hint": "URL-friendly identifier (auto-generated from title)"
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"name": "excerpt",
|
|
28
|
-
"type": "text",
|
|
29
|
-
"label": "Excerpt",
|
|
30
|
-
"hint": "Short summary for the content"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"name": "content",
|
|
34
|
-
"type": "richtext",
|
|
35
|
-
"output": "html",
|
|
36
|
-
"height": "fill"
|
|
37
|
-
}
|
|
38
|
-
]
|
|
39
|
-
},
|
|
40
|
-
"sidebar": {
|
|
41
|
-
"fields": [
|
|
42
|
-
{
|
|
43
|
-
"name": "generalSidebar",
|
|
44
|
-
"type": "section",
|
|
45
|
-
"heading": {
|
|
46
|
-
"icon": "bolt",
|
|
47
|
-
"title": "General"
|
|
48
|
-
},
|
|
49
|
-
"fields": [
|
|
16
|
+
"name": "postTabs",
|
|
17
|
+
"type": "tabs",
|
|
18
|
+
"tabs": [
|
|
50
19
|
{
|
|
51
|
-
"name": "
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
20
|
+
"name": "content",
|
|
21
|
+
"label": "Content",
|
|
22
|
+
"icon": "file-text",
|
|
23
|
+
"slot": {
|
|
24
|
+
"main": {
|
|
25
|
+
"fields": [
|
|
26
|
+
{
|
|
27
|
+
"name": "title",
|
|
28
|
+
"type": "string",
|
|
29
|
+
"label": "Title",
|
|
30
|
+
"required": true
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "slug",
|
|
34
|
+
"type": "string",
|
|
35
|
+
"label": "Slug",
|
|
36
|
+
"hint": "URL-friendly identifier (auto-generated from title)"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "excerpt",
|
|
40
|
+
"type": "text",
|
|
41
|
+
"label": "Excerpt",
|
|
42
|
+
"hint": "Short summary for the content"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "content",
|
|
46
|
+
"type": "richtext",
|
|
47
|
+
"output": "html",
|
|
48
|
+
"height": "fill"
|
|
49
|
+
}
|
|
50
|
+
]
|
|
69
51
|
},
|
|
70
|
-
{
|
|
71
|
-
"
|
|
72
|
-
|
|
52
|
+
"sidebar": {
|
|
53
|
+
"fields": [
|
|
54
|
+
{
|
|
55
|
+
"name": "generalSidebar",
|
|
56
|
+
"type": "section",
|
|
57
|
+
"heading": {
|
|
58
|
+
"icon": "bolt",
|
|
59
|
+
"title": "General"
|
|
60
|
+
},
|
|
61
|
+
"fields": [
|
|
62
|
+
{
|
|
63
|
+
"name": "coverImage",
|
|
64
|
+
"type": "image",
|
|
65
|
+
"label": "Cover Image"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "categories",
|
|
69
|
+
"type": "select",
|
|
70
|
+
"label": "Categories",
|
|
71
|
+
"placeholder": "Select categories",
|
|
72
|
+
"hint": "Assign one or more categories",
|
|
73
|
+
"default": "category-1",
|
|
74
|
+
"creatable": true,
|
|
75
|
+
"multiple": true,
|
|
76
|
+
"previewLimit": 1,
|
|
77
|
+
"options": [
|
|
78
|
+
{
|
|
79
|
+
"label": "Category 1",
|
|
80
|
+
"value": "category-1"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"label": "Category 2",
|
|
84
|
+
"value": "category-2"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
]
|
|
73
91
|
}
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
]
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
"name": "seoSidebar",
|
|
80
|
-
"type": "section",
|
|
81
|
-
"heading": {
|
|
82
|
-
"icon": "globe",
|
|
83
|
-
"title": "SEO Settings"
|
|
84
|
-
},
|
|
85
|
-
"fields": [
|
|
86
|
-
{
|
|
87
|
-
"name": "openGraphImage",
|
|
88
|
-
"type": "image",
|
|
89
|
-
"label": "OpenGraph Image"
|
|
92
|
+
}
|
|
90
93
|
},
|
|
91
94
|
{
|
|
92
|
-
"name": "
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
95
|
+
"name": "seo",
|
|
96
|
+
"label": "SEO",
|
|
97
|
+
"icon": "globe",
|
|
98
|
+
"slot": {
|
|
99
|
+
"main": {
|
|
100
|
+
"fields": [
|
|
101
|
+
{
|
|
102
|
+
"name": "seoTitle",
|
|
103
|
+
"type": "string",
|
|
104
|
+
"label": "SEO Title",
|
|
105
|
+
"defaultValueFrom": "title",
|
|
106
|
+
"hint": "Overrides the post title in search results",
|
|
107
|
+
"length": 70
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"name": "seoDescription",
|
|
111
|
+
"type": "text",
|
|
112
|
+
"label": "SEO Description",
|
|
113
|
+
"defaultValueFrom": "excerpt",
|
|
114
|
+
"hint": "Overrides the excerpt in search result snippets"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "noIndex",
|
|
118
|
+
"type": "boolean",
|
|
119
|
+
"label": "No Index",
|
|
120
|
+
"hint": "Ask search engines not to index this post",
|
|
121
|
+
"default": false
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "noFollow",
|
|
125
|
+
"type": "boolean",
|
|
126
|
+
"label": "No Follow",
|
|
127
|
+
"hint": "Ask search engines not to follow links on this post",
|
|
128
|
+
"default": false
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
"sidebar": {
|
|
133
|
+
"fields": [
|
|
134
|
+
{
|
|
135
|
+
"name": "seoSidebar",
|
|
136
|
+
"type": "section",
|
|
137
|
+
"heading": {
|
|
138
|
+
"icon": "globe",
|
|
139
|
+
"title": "SEO Settings"
|
|
140
|
+
},
|
|
141
|
+
"fields": [
|
|
142
|
+
{
|
|
143
|
+
"name": "openGraphImage",
|
|
144
|
+
"type": "image",
|
|
145
|
+
"label": "OpenGraph Image"
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
}
|
|
119
152
|
}
|
|
120
153
|
]
|
|
121
154
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { BetterstartPluginDefinition } from '@plugin-engine/types.js'
|
|
2
|
+
|
|
3
|
+
export const portfolioPlugin: BetterstartPluginDefinition = {
|
|
4
|
+
id: 'portfolio',
|
|
5
|
+
title: 'Portfolio',
|
|
6
|
+
description: 'Portfolio content module',
|
|
7
|
+
kind: 'content',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
dependencies: [],
|
|
10
|
+
conflicts: [],
|
|
11
|
+
schemaFiles: ['portfolio.json'],
|
|
12
|
+
files: [],
|
|
13
|
+
packageDependencies: [],
|
|
14
|
+
devDependencies: [],
|
|
15
|
+
envSections: [],
|
|
16
|
+
configure: 'none'
|
|
17
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "portfolio",
|
|
3
|
+
"type": "entity",
|
|
4
|
+
"label": "Portfolio",
|
|
5
|
+
"description": "Manage portfolio items",
|
|
6
|
+
"icon": "Briefcase",
|
|
7
|
+
"navGroup": {
|
|
8
|
+
"label": "Collections",
|
|
9
|
+
"position": 0
|
|
10
|
+
},
|
|
11
|
+
"navPosition": 1,
|
|
12
|
+
"slot": {
|
|
13
|
+
"main": {
|
|
14
|
+
"fields": [
|
|
15
|
+
{
|
|
16
|
+
"name": "title",
|
|
17
|
+
"type": "string",
|
|
18
|
+
"label": "Title",
|
|
19
|
+
"required": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": "eyebrow",
|
|
23
|
+
"type": "string",
|
|
24
|
+
"label": "Eyebrow",
|
|
25
|
+
"required": true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "brandLink",
|
|
29
|
+
"type": "string",
|
|
30
|
+
"label": "Brand Link",
|
|
31
|
+
"required": false
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "gallery",
|
|
35
|
+
"type": "gallery",
|
|
36
|
+
"label": "Gallery"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "description",
|
|
40
|
+
"type": "richtext",
|
|
41
|
+
"label": "Description",
|
|
42
|
+
"required": false,
|
|
43
|
+
"output": "html",
|
|
44
|
+
"height": "fill"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"sidebar": {
|
|
49
|
+
"fields": [
|
|
50
|
+
{
|
|
51
|
+
"name": "generalSidebar",
|
|
52
|
+
"type": "section",
|
|
53
|
+
"heading": {
|
|
54
|
+
"icon": "bolt",
|
|
55
|
+
"title": "General"
|
|
56
|
+
},
|
|
57
|
+
"fields": [
|
|
58
|
+
{
|
|
59
|
+
"name": "coverImage",
|
|
60
|
+
"type": "image",
|
|
61
|
+
"label": "Cover Image"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "categories",
|
|
65
|
+
"type": "select",
|
|
66
|
+
"label": "Categories",
|
|
67
|
+
"placeholder": "Select categories",
|
|
68
|
+
"hint": "Assign one or more categories",
|
|
69
|
+
"default": "category-1",
|
|
70
|
+
"creatable": true,
|
|
71
|
+
"multiple": true,
|
|
72
|
+
"previewLimit": 1,
|
|
73
|
+
"options": [
|
|
74
|
+
{
|
|
75
|
+
"label": "Category 1",
|
|
76
|
+
"value": "category-1"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"label": "Category 2",
|
|
80
|
+
"value": "category-2"
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"columns": [
|
|
90
|
+
{
|
|
91
|
+
"accessorKey": "title",
|
|
92
|
+
"header": "Title",
|
|
93
|
+
"type": "text",
|
|
94
|
+
"sortable": true,
|
|
95
|
+
"size": "xl"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"accessorKey": "published",
|
|
99
|
+
"header": "Status",
|
|
100
|
+
"type": "boolean",
|
|
101
|
+
"sortable": true,
|
|
102
|
+
"size": "sm"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"accessorKey": "updatedAt",
|
|
106
|
+
"header": "Updated",
|
|
107
|
+
"type": "date",
|
|
108
|
+
"sortable": true,
|
|
109
|
+
"size": "sm"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"accessorKey": "createdAt",
|
|
113
|
+
"header": "Created",
|
|
114
|
+
"type": "date",
|
|
115
|
+
"sortable": true,
|
|
116
|
+
"size": "sm"
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
"actions": {
|
|
120
|
+
"create": true,
|
|
121
|
+
"edit": true,
|
|
122
|
+
"delete": true,
|
|
123
|
+
"draft": true
|
|
124
|
+
},
|
|
125
|
+
"search": {
|
|
126
|
+
"fields": ["title", "excerpt"]
|
|
127
|
+
}
|
|
128
|
+
}
|
package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/dev-mode-types.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type DevModeSnippetIcon =
|
|
|
10
10
|
| 'save'
|
|
11
11
|
| 'send'
|
|
12
12
|
| 'trash'
|
|
13
|
-
export type DevModeSnippetKind = 'query' | 'mutation'
|
|
13
|
+
export type DevModeSnippetKind = 'jsx' | 'query' | 'mutation'
|
|
14
14
|
export type DevModeLifecycleHookPhase = 'before' | 'after'
|
|
15
15
|
export type DevModeLifecycleHookEvent =
|
|
16
16
|
| 'beforeCreate'
|
|
@@ -33,7 +33,7 @@ export interface DevModeSnippet {
|
|
|
33
33
|
code: string
|
|
34
34
|
codeTabs?: DevModeSnippetCodeTab[]
|
|
35
35
|
payloadExample?: DevModeSnippetExample
|
|
36
|
-
responseExample
|
|
36
|
+
responseExample?: DevModeSnippetExample
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export interface DevModeSnippetCodeTab {
|
|
@@ -49,7 +49,7 @@ export function DevModeIntegrateButton({
|
|
|
49
49
|
<Drawer direction="right" handleOnly onOpenChange={handleOpenChange}>
|
|
50
50
|
<DrawerTrigger asChild>
|
|
51
51
|
<Button type="button" variant="outline">
|
|
52
|
-
<Code2
|
|
52
|
+
<Code2 />
|
|
53
53
|
<span className="hidden sm:inline">Dev Mode</span>
|
|
54
54
|
</Button>
|
|
55
55
|
</DrawerTrigger>
|
package/dist/assets/adapters/next/templates/init/components/shared/media/media-delete-dialog.tsx
CHANGED
|
@@ -53,7 +53,7 @@ export function MediaDeleteDialog({ media, disabled = false, onDeleted }: MediaD
|
|
|
53
53
|
<AlertDialog>
|
|
54
54
|
<AlertDialogTrigger asChild>
|
|
55
55
|
<Button variant="destructive" disabled={disabled || isPending}>
|
|
56
|
-
<Trash2
|
|
56
|
+
<Trash2 />
|
|
57
57
|
Delete media
|
|
58
58
|
</Button>
|
|
59
59
|
</AlertDialogTrigger>
|
package/dist/assets/adapters/next/templates/init/components/shared/media/media-delete-drawer.tsx
CHANGED
|
@@ -97,7 +97,7 @@ export function MediaDeleteDrawer({
|
|
|
97
97
|
>
|
|
98
98
|
<DrawerPrimitive.Trigger asChild>
|
|
99
99
|
<Button variant="destructive" disabled={disabled || isPending || !container}>
|
|
100
|
-
<Trash2
|
|
100
|
+
<Trash2 />
|
|
101
101
|
Delete File
|
|
102
102
|
</Button>
|
|
103
103
|
</DrawerPrimitive.Trigger>
|
package/dist/assets/adapters/next/templates/init/components/shared/media/media-grid-item.tsx
CHANGED
|
@@ -11,7 +11,7 @@ interface MediaGridItemProps {
|
|
|
11
11
|
item: AdminMedia
|
|
12
12
|
selected?: boolean
|
|
13
13
|
isSelectMode?: boolean
|
|
14
|
-
onClick
|
|
14
|
+
onClick?: (item: AdminMedia) => void
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export const MediaGridItem = React.memo(function MediaGridItem({
|
|
@@ -21,10 +21,16 @@ export const MediaGridItem = React.memo(function MediaGridItem({
|
|
|
21
21
|
onClick
|
|
22
22
|
}: MediaGridItemProps) {
|
|
23
23
|
return (
|
|
24
|
-
<Card
|
|
24
|
+
<Card
|
|
25
|
+
className={cn('relative group', {
|
|
26
|
+
'cursor-pointer': Boolean(onClick)
|
|
27
|
+
})}
|
|
28
|
+
onClick={onClick ? () => onClick(item) : undefined}
|
|
29
|
+
>
|
|
25
30
|
<CardContent
|
|
26
|
-
aria-pressed={isSelectMode ? selected : undefined}
|
|
27
|
-
className={cn('p-2 flex flex-col
|
|
31
|
+
aria-pressed={isSelectMode && onClick ? selected : undefined}
|
|
32
|
+
className={cn('p-2 flex flex-col', {
|
|
33
|
+
'hover:border-highlight': Boolean(onClick),
|
|
28
34
|
'border-highlight': selected
|
|
29
35
|
})}
|
|
30
36
|
>
|
|
@@ -32,7 +38,7 @@ export const MediaGridItem = React.memo(function MediaGridItem({
|
|
|
32
38
|
<MediaPreview media={item} isFilled />
|
|
33
39
|
</div>
|
|
34
40
|
|
|
35
|
-
{isSelectMode && (
|
|
41
|
+
{isSelectMode && onClick ? (
|
|
36
42
|
<Checkbox
|
|
37
43
|
aria-label={selected ? `Deselect ${item.filename}` : `Select ${item.filename}`}
|
|
38
44
|
tabIndex={-1}
|
|
@@ -42,10 +48,14 @@ export const MediaGridItem = React.memo(function MediaGridItem({
|
|
|
42
48
|
checked={selected}
|
|
43
49
|
onCheckedChange={() => onClick(item)}
|
|
44
50
|
/>
|
|
45
|
-
)}
|
|
51
|
+
) : null}
|
|
46
52
|
</CardContent>
|
|
47
53
|
<CardFooter>
|
|
48
|
-
<span
|
|
54
|
+
<span
|
|
55
|
+
className={cn('w-full truncate text-sm text-muted-foreground', {
|
|
56
|
+
'group-hover:text-foreground': Boolean(onClick)
|
|
57
|
+
})}
|
|
58
|
+
>
|
|
49
59
|
{item.filename}
|
|
50
60
|
</span>
|
|
51
61
|
</CardFooter>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AdminNavigationItem } from '@admin/types/navigation'
|
|
2
2
|
import { House, ImagePlay } from 'lucide-react'
|
|
3
3
|
import { menusNav } from './navigation/menus'
|
|
4
|
+
import { portfolioNav } from './navigation/portfolio'
|
|
4
5
|
import { postsNav } from './navigation/posts'
|
|
5
6
|
|
|
6
7
|
export type { AdminNavigationItem } from '@admin/types/navigation'
|
|
@@ -29,7 +30,7 @@ function comparePositions(a?: number, b?: number): number {
|
|
|
29
30
|
return 0
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
const combinedNavigation = [...coreNav, ...menusNav, ...postsNav]
|
|
33
|
+
const combinedNavigation = [...coreNav, ...menusNav, ...portfolioNav, ...postsNav]
|
|
33
34
|
|
|
34
35
|
const dashboard = combinedNavigation.find((item) => item.href === '/admin')
|
|
35
36
|
const others = combinedNavigation.filter((item) => item.href !== '/admin')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { MediaField } from '@admin/components/custom/media-field'
|
|
4
4
|
import { useTheme } from '@admin/hooks/use-admin-theme'
|
|
5
5
|
import type { ContentEditorSelectionRequest } from '@admin/utils/editor/content-editor'
|
|
6
6
|
import {
|
|
@@ -73,7 +73,7 @@ class MarkdownMediaGalleryWidget extends WidgetType {
|
|
|
73
73
|
root.render(
|
|
74
74
|
<QueryClientProvider client={this.props.queryClient}>
|
|
75
75
|
<NuqsAdapter>
|
|
76
|
-
<
|
|
76
|
+
<MediaField
|
|
77
77
|
value=""
|
|
78
78
|
valueMode="url"
|
|
79
79
|
accept="image/*"
|
|
@@ -95,7 +95,7 @@ class MarkdownMediaGalleryWidget extends WidgetType {
|
|
|
95
95
|
root.render(
|
|
96
96
|
<QueryClientProvider client={this.props.queryClient}>
|
|
97
97
|
<NuqsAdapter>
|
|
98
|
-
<
|
|
98
|
+
<MediaField
|
|
99
99
|
value=""
|
|
100
100
|
valueMode="url"
|
|
101
101
|
accept="image/*"
|
|
@@ -97,6 +97,7 @@ export function useMediaByIds(ids: string[]) {
|
|
|
97
97
|
return useQuery<(AdminMedia | null)[]>({
|
|
98
98
|
queryKey: ['media', 'batch', ids],
|
|
99
99
|
queryFn: () => (ids.length > 0 ? getMediaByIds(ids) : []),
|
|
100
|
-
enabled: ids.length > 0
|
|
100
|
+
enabled: ids.length > 0,
|
|
101
|
+
placeholderData: (previousData) => previousData
|
|
101
102
|
})
|
|
102
103
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { invalidateUsersCache, isEmailConfigured, updateEmail } from '@admin/actions/profile'
|
|
4
4
|
import { authClient } from '@admin/auth/client'
|
|
5
|
-
import {
|
|
5
|
+
import { MediaField } from '@admin/components/custom/media-field'
|
|
6
6
|
import { Avatar, AvatarFallback, AvatarImage } from '@admin/components/ui/avatar'
|
|
7
7
|
import { Button } from '@admin/components/ui/button'
|
|
8
8
|
import {
|
|
@@ -157,7 +157,7 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
157
157
|
</div>
|
|
158
158
|
</div>
|
|
159
159
|
</CardHeader>
|
|
160
|
-
<CardContent className="space-y-
|
|
160
|
+
<CardContent className="space-y-5">
|
|
161
161
|
<FormField
|
|
162
162
|
control={profileForm.control}
|
|
163
163
|
name="image"
|
|
@@ -165,7 +165,7 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
165
165
|
<FormItem>
|
|
166
166
|
<FormLabel>Profile Picture</FormLabel>
|
|
167
167
|
<FormControl>
|
|
168
|
-
<
|
|
168
|
+
<MediaField
|
|
169
169
|
value={formField.value}
|
|
170
170
|
onChange={formField.onChange}
|
|
171
171
|
onBlur={formField.onBlur}
|
|
@@ -91,12 +91,17 @@ export interface PaginatedResponse<T> {
|
|
|
91
91
|
totalPages: number
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
type TableRowId<TData extends import('@tanstack/react-table').RowData> = TData extends {
|
|
95
|
+
id: infer TId
|
|
96
|
+
}
|
|
97
|
+
? TId
|
|
98
|
+
: string
|
|
99
|
+
|
|
94
100
|
/** TanStack Table meta augmentation */
|
|
95
101
|
declare module '@tanstack/react-table' {
|
|
96
|
-
// biome-ignore lint/correctness/noUnusedVariables: augmenting module
|
|
97
102
|
interface TableMeta<TData extends import('@tanstack/react-table').RowData> {
|
|
98
103
|
reorderMode?: boolean
|
|
99
|
-
onMoveRow?: (id:
|
|
104
|
+
onMoveRow?: (id: TableRowId<TData>, direction: 'up' | 'down') => void
|
|
100
105
|
currentUser?: {
|
|
101
106
|
id: string
|
|
102
107
|
email: string
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { MediaField } from '@admin/components/custom/media-field'
|
|
4
4
|
|
|
5
5
|
export interface ContentEditorMediaGalleryBlockProps {
|
|
6
6
|
accept?: string
|
|
@@ -16,7 +16,7 @@ export function ContentEditorMediaGalleryBlock({
|
|
|
16
16
|
onRemove
|
|
17
17
|
}: ContentEditorMediaGalleryBlockProps) {
|
|
18
18
|
return (
|
|
19
|
-
<
|
|
19
|
+
<MediaField
|
|
20
20
|
value=""
|
|
21
21
|
onChange={(url) => {
|
|
22
22
|
if (url) onMediaSelected(url)
|
|
@@ -24,7 +24,7 @@ export function TableAddControls({ controls }: TableAddControlsProps) {
|
|
|
24
24
|
variant="outline"
|
|
25
25
|
>
|
|
26
26
|
<span className="pointer-events-none inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-border bg-input text-foreground transition-colors group-hover:bg-secondary group-focus-visible:bg-secondary">
|
|
27
|
-
<PlusIcon aria-hidden="true"
|
|
27
|
+
<PlusIcon aria-hidden="true" />
|
|
28
28
|
</span>
|
|
29
29
|
</Button>
|
|
30
30
|
<Button
|
|
@@ -37,7 +37,7 @@ export function TableAddControls({ controls }: TableAddControlsProps) {
|
|
|
37
37
|
variant="outline"
|
|
38
38
|
>
|
|
39
39
|
<span className="pointer-events-none inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-border bg-input text-foreground transition-colors group-hover:bg-secondary group-focus-visible:bg-secondary">
|
|
40
|
-
<PlusIcon aria-hidden="true"
|
|
40
|
+
<PlusIcon aria-hidden="true" />
|
|
41
41
|
</span>
|
|
42
42
|
</Button>
|
|
43
43
|
</div>,
|