@byline/host-tanstack-start 3.5.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin-shell/admin-roles/list.js +1 -0
- package/dist/admin-shell/collections/create.js +11 -2
- package/dist/routes/create-collection-edit-route.js +48 -2
- package/dist/server-fns/collections/create.d.ts +2 -0
- package/dist/server-fns/collections/create.js +4 -2
- package/package.json +8 -8
- package/src/admin-shell/admin-roles/list.tsx +1 -0
- package/src/admin-shell/collections/create.tsx +18 -6
- package/src/routes/create-collection-edit-route.tsx +42 -1
- package/src/server-fns/collections/create.ts +8 -2
|
@@ -220,6 +220,7 @@ function AdminRolesListView({ data }) {
|
|
|
220
220
|
orderChanged ? /*#__PURE__*/ jsx("div", {
|
|
221
221
|
className: classnames('byline-roles-list-save', list_module.save),
|
|
222
222
|
children: /*#__PURE__*/ jsx("form", {
|
|
223
|
+
method: "post",
|
|
223
224
|
onSubmit: handleOnSave,
|
|
224
225
|
noValidate: true,
|
|
225
226
|
className: classnames('byline-roles-list-save-form', list_module.saveForm),
|
|
@@ -17,7 +17,7 @@ const CreateView = ({ collectionDefinition, adminConfig, initialData })=>{
|
|
|
17
17
|
const { labels, path, fields } = collectionDefinition;
|
|
18
18
|
const handleSubmit = async ({ data, systemPath, systemAvailableLocales })=>{
|
|
19
19
|
try {
|
|
20
|
-
await createCollectionDocument({
|
|
20
|
+
const result = await createCollectionDocument({
|
|
21
21
|
data: {
|
|
22
22
|
collection: path,
|
|
23
23
|
data,
|
|
@@ -29,7 +29,16 @@ const CreateView = ({ collectionDefinition, adminConfig, initialData })=>{
|
|
|
29
29
|
} : {}
|
|
30
30
|
}
|
|
31
31
|
});
|
|
32
|
-
navigate({
|
|
32
|
+
result?.documentId ? navigate({
|
|
33
|
+
to: '/admin/collections/$collection/$id',
|
|
34
|
+
params: {
|
|
35
|
+
collection: path,
|
|
36
|
+
id: result.documentId
|
|
37
|
+
},
|
|
38
|
+
search: {
|
|
39
|
+
action: 'created'
|
|
40
|
+
}
|
|
41
|
+
}) : navigate({
|
|
33
42
|
to: '/admin/collections/$collection',
|
|
34
43
|
params: {
|
|
35
44
|
collection: path
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
2
3
|
import { createFileRoute, notFound } from "@tanstack/react-router";
|
|
3
4
|
import { getCollectionAdminConfig, getCollectionDefinition } from "@byline/core";
|
|
4
5
|
import { useTranslation } from "@byline/i18n/react";
|
|
6
|
+
import { useToastManager } from "@byline/ui/react";
|
|
5
7
|
import { z } from "zod";
|
|
6
8
|
import { BreadcrumbsClient } from "../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js";
|
|
9
|
+
import { useNavigate } from "../admin-shell/chrome/loose-router.js";
|
|
7
10
|
import { EditView } from "../admin-shell/collections/edit.js";
|
|
8
11
|
import { getCollectionDocument } from "../server-fns/collections/index.js";
|
|
9
12
|
const searchSchema = z.object({
|
|
10
|
-
locale: z.string().optional()
|
|
13
|
+
locale: z.string().optional(),
|
|
14
|
+
action: z["enum"]([
|
|
15
|
+
'created'
|
|
16
|
+
]).optional()
|
|
11
17
|
});
|
|
12
18
|
function createCollectionEditRoute(path, opts) {
|
|
13
19
|
const Route = createFileRoute(path)({
|
|
@@ -28,10 +34,50 @@ function createCollectionEditRoute(path, opts) {
|
|
|
28
34
|
component: function() {
|
|
29
35
|
const data = Route.useLoaderData();
|
|
30
36
|
const { collection, id } = Route.useParams();
|
|
31
|
-
const
|
|
37
|
+
const search = Route.useSearch();
|
|
38
|
+
const { locale } = search;
|
|
32
39
|
const collectionDef = getCollectionDefinition(collection);
|
|
33
40
|
const adminConfig = getCollectionAdminConfig(collection);
|
|
34
41
|
const { t } = useTranslation('byline-admin');
|
|
42
|
+
const toastManager = useToastManager();
|
|
43
|
+
const navigate = useNavigate();
|
|
44
|
+
const createdToastFiredRef = useRef(false);
|
|
45
|
+
useEffect(()=>{
|
|
46
|
+
if ('created' !== search.action) {
|
|
47
|
+
createdToastFiredRef.current = false;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (createdToastFiredRef.current) return;
|
|
51
|
+
createdToastFiredRef.current = true;
|
|
52
|
+
toastManager.add({
|
|
53
|
+
title: t('collections.list.createdToastTitle', {
|
|
54
|
+
label: collectionDef.labels.singular
|
|
55
|
+
}),
|
|
56
|
+
description: t("collections.list.createdToastDescription", {
|
|
57
|
+
label: collectionDef.labels.singular.toLowerCase()
|
|
58
|
+
}),
|
|
59
|
+
data: {
|
|
60
|
+
intent: 'success',
|
|
61
|
+
iconType: 'success',
|
|
62
|
+
icon: true,
|
|
63
|
+
close: true
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
navigate({
|
|
67
|
+
to: '.',
|
|
68
|
+
search: (prev)=>({
|
|
69
|
+
...prev,
|
|
70
|
+
action: void 0
|
|
71
|
+
}),
|
|
72
|
+
replace: true
|
|
73
|
+
});
|
|
74
|
+
}, [
|
|
75
|
+
search.action,
|
|
76
|
+
navigate,
|
|
77
|
+
toastManager.add,
|
|
78
|
+
collectionDef.labels.singular,
|
|
79
|
+
t
|
|
80
|
+
]);
|
|
35
81
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
36
82
|
children: [
|
|
37
83
|
/*#__PURE__*/ jsx(BreadcrumbsClient, {
|
|
@@ -27,7 +27,7 @@ const createCollectionDocument = createServerFn({
|
|
|
27
27
|
slugifier: serverConfig.slugifier,
|
|
28
28
|
requestContext: await getAdminRequestContext()
|
|
29
29
|
};
|
|
30
|
-
await createDocument(ctx, {
|
|
30
|
+
const result = await createDocument(ctx, {
|
|
31
31
|
data: structuredClone(documentData),
|
|
32
32
|
status: documentData.status,
|
|
33
33
|
locale: locale ?? serverConfig.i18n.content.defaultLocale,
|
|
@@ -35,7 +35,9 @@ const createCollectionDocument = createServerFn({
|
|
|
35
35
|
availableLocales
|
|
36
36
|
});
|
|
37
37
|
return {
|
|
38
|
-
status: 'ok'
|
|
38
|
+
status: 'ok',
|
|
39
|
+
documentId: result.documentId,
|
|
40
|
+
documentVersionId: result.documentVersionId
|
|
39
41
|
};
|
|
40
42
|
});
|
|
41
43
|
export { createCollectionDocument };
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"private": false,
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
|
-
"version": "3.
|
|
6
|
+
"version": "3.6.0",
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": ">=20.9.0"
|
|
9
9
|
},
|
|
@@ -115,13 +115,13 @@
|
|
|
115
115
|
"react-swipeable": "^7.0.2",
|
|
116
116
|
"uuid": "^14.0.0",
|
|
117
117
|
"zod": "^4.4.3",
|
|
118
|
-
"@byline/
|
|
119
|
-
"@byline/
|
|
120
|
-
"@byline/
|
|
121
|
-
"@byline/
|
|
122
|
-
"@byline/
|
|
123
|
-
"@byline/i18n": "3.
|
|
124
|
-
"@byline/
|
|
118
|
+
"@byline/admin": "3.6.0",
|
|
119
|
+
"@byline/client": "3.6.0",
|
|
120
|
+
"@byline/ai": "3.6.0",
|
|
121
|
+
"@byline/core": "3.6.0",
|
|
122
|
+
"@byline/ui": "3.6.0",
|
|
123
|
+
"@byline/i18n": "3.6.0",
|
|
124
|
+
"@byline/auth": "3.6.0"
|
|
125
125
|
},
|
|
126
126
|
"peerDependencies": {
|
|
127
127
|
"@tanstack/react-router": "^1.167.0",
|
|
@@ -264,6 +264,7 @@ export function AdminRolesListView({ data }: { data: AdminRoleListResponse }) {
|
|
|
264
264
|
{orderChanged ? (
|
|
265
265
|
<div className={cx('byline-roles-list-save', styles.save)}>
|
|
266
266
|
<form
|
|
267
|
+
method="post"
|
|
267
268
|
onSubmit={handleOnSave}
|
|
268
269
|
noValidate
|
|
269
270
|
className={cx('byline-roles-list-save-form', styles.saveForm)}
|
|
@@ -52,7 +52,7 @@ export const CreateView = ({
|
|
|
52
52
|
systemAvailableLocales?: string[]
|
|
53
53
|
}) => {
|
|
54
54
|
try {
|
|
55
|
-
await createCollectionDocument({
|
|
55
|
+
const result = await createCollectionDocument({
|
|
56
56
|
data: {
|
|
57
57
|
collection: path,
|
|
58
58
|
data,
|
|
@@ -60,11 +60,23 @@ export const CreateView = ({
|
|
|
60
60
|
...(systemAvailableLocales ? { availableLocales: systemAvailableLocales } : {}),
|
|
61
61
|
},
|
|
62
62
|
})
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
// Create → edit: land the editor on the new document, where the rest
|
|
64
|
+
// of the work (content, status, relations) happens. The list-view
|
|
65
|
+
// fallback covers callers running against an older server fn that
|
|
66
|
+
// doesn't return the new document's id.
|
|
67
|
+
if (result?.documentId) {
|
|
68
|
+
navigate({
|
|
69
|
+
to: '/admin/collections/$collection/$id' as never,
|
|
70
|
+
params: { collection: path, id: result.documentId } as never,
|
|
71
|
+
search: { action: 'created' },
|
|
72
|
+
})
|
|
73
|
+
} else {
|
|
74
|
+
navigate({
|
|
75
|
+
to: '/admin/collections/$collection' as never,
|
|
76
|
+
params: { collection: path },
|
|
77
|
+
search: { action: 'created' },
|
|
78
|
+
})
|
|
79
|
+
}
|
|
68
80
|
} catch (err) {
|
|
69
81
|
console.error(err)
|
|
70
82
|
|
|
@@ -6,20 +6,25 @@
|
|
|
6
6
|
* Copyright (c) Infonomic Company Limited
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { useEffect, useRef } from 'react'
|
|
9
10
|
import { createFileRoute, notFound } from '@tanstack/react-router'
|
|
10
11
|
|
|
11
12
|
import type { CollectionDefinition } from '@byline/core'
|
|
12
13
|
import { getCollectionAdminConfig, getCollectionDefinition } from '@byline/core'
|
|
13
14
|
import { useTranslation } from '@byline/i18n/react'
|
|
15
|
+
import { useToastManager } from '@byline/ui/react'
|
|
14
16
|
import { z } from 'zod'
|
|
15
17
|
|
|
16
18
|
import { BreadcrumbsClient } from '../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js'
|
|
19
|
+
import { useNavigate } from '../admin-shell/chrome/loose-router.js'
|
|
17
20
|
import { EditView } from '../admin-shell/collections/edit.js'
|
|
18
21
|
import { getCollectionDocument } from '../server-fns/collections/index.js'
|
|
19
22
|
import type { ContentLocaleOption } from '../admin-shell/collections/view-menu.js'
|
|
20
23
|
|
|
21
24
|
const searchSchema = z.object({
|
|
22
25
|
locale: z.string().optional(),
|
|
26
|
+
/** Set by the create view's create → edit redirect; fires the created toast. */
|
|
27
|
+
action: z.enum(['created']).optional(),
|
|
23
28
|
})
|
|
24
29
|
|
|
25
30
|
interface CollectionEditOpts {
|
|
@@ -70,10 +75,46 @@ export function createCollectionEditRoute(path: string, opts: CollectionEditOpts
|
|
|
70
75
|
component: function CollectionEditComponent() {
|
|
71
76
|
const data = Route.useLoaderData()
|
|
72
77
|
const { collection, id } = Route.useParams() as { collection: string; id: string }
|
|
73
|
-
const
|
|
78
|
+
const search = Route.useSearch() as z.infer<typeof searchSchema>
|
|
79
|
+
const { locale } = search
|
|
74
80
|
const collectionDef = getCollectionDefinition(collection) as CollectionDefinition
|
|
75
81
|
const adminConfig = getCollectionAdminConfig(collection)
|
|
76
82
|
const { t } = useTranslation('byline-admin')
|
|
83
|
+
const toastManager = useToastManager()
|
|
84
|
+
const navigate = useNavigate()
|
|
85
|
+
|
|
86
|
+
// Post-create toast for the create → edit redirect (?action=created).
|
|
87
|
+
// Ref-guarded for the same reason as the list route's created toast:
|
|
88
|
+
// `toastManager` changes identity on every add, so the effect depends
|
|
89
|
+
// on the stable `toastManager.add` and the ref protects against any
|
|
90
|
+
// re-fire that observes the search param before navigate clears it.
|
|
91
|
+
const createdToastFiredRef = useRef(false)
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (search.action !== 'created') {
|
|
94
|
+
createdToastFiredRef.current = false
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
if (createdToastFiredRef.current) return
|
|
98
|
+
createdToastFiredRef.current = true
|
|
99
|
+
|
|
100
|
+
toastManager.add({
|
|
101
|
+
title: t('collections.list.createdToastTitle', { label: collectionDef.labels.singular }),
|
|
102
|
+
description: t('collections.list.createdToastDescription', {
|
|
103
|
+
label: collectionDef.labels.singular.toLowerCase(),
|
|
104
|
+
}),
|
|
105
|
+
data: {
|
|
106
|
+
intent: 'success',
|
|
107
|
+
iconType: 'success',
|
|
108
|
+
icon: true,
|
|
109
|
+
close: true,
|
|
110
|
+
},
|
|
111
|
+
})
|
|
112
|
+
navigate({
|
|
113
|
+
to: '.',
|
|
114
|
+
search: (prev: Record<string, unknown>) => ({ ...prev, action: undefined }),
|
|
115
|
+
replace: true,
|
|
116
|
+
})
|
|
117
|
+
}, [search.action, navigate, toastManager.add, collectionDef.labels.singular, t])
|
|
77
118
|
|
|
78
119
|
return (
|
|
79
120
|
<>
|
|
@@ -59,7 +59,7 @@ export const createCollectionDocument = createServerFn({ method: 'POST' })
|
|
|
59
59
|
requestContext: await getAdminRequestContext(),
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
await createDocument(ctx, {
|
|
62
|
+
const result = await createDocument(ctx, {
|
|
63
63
|
data: structuredClone(documentData),
|
|
64
64
|
status: documentData.status,
|
|
65
65
|
locale: locale ?? serverConfig.i18n.content.defaultLocale,
|
|
@@ -67,5 +67,11 @@ export const createCollectionDocument = createServerFn({ method: 'POST' })
|
|
|
67
67
|
availableLocales,
|
|
68
68
|
})
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
// The new document's id is returned so the create view can navigate
|
|
71
|
+
// straight to the edit view (create → edit).
|
|
72
|
+
return {
|
|
73
|
+
status: 'ok' as const,
|
|
74
|
+
documentId: result.documentId,
|
|
75
|
+
documentVersionId: result.documentVersionId,
|
|
76
|
+
}
|
|
71
77
|
})
|