@byline/host-tanstack-start 3.0.0 → 3.0.2
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/collections/edit.js +65 -1
- package/dist/server-fns/collections/delete-locale.d.ts +27 -0
- package/dist/server-fns/collections/delete-locale.js +35 -0
- package/dist/server-fns/collections/index.d.ts +1 -0
- package/dist/server-fns/collections/index.js +1 -0
- package/package.json +8 -8
- package/src/admin-shell/collections/edit.tsx +54 -0
- package/src/server-fns/collections/delete-locale.ts +59 -0
- package/src/server-fns/collections/get.ts +1 -1
- package/src/server-fns/collections/index.ts +1 -0
|
@@ -4,7 +4,7 @@ import { FormRenderer } from "@byline/admin/react";
|
|
|
4
4
|
import { getDefaultStatus, getWorkflowStatuses } from "@byline/core";
|
|
5
5
|
import { useTranslation } from "@byline/i18n/react";
|
|
6
6
|
import { Container, Section, useToastManager } from "@byline/ui/react";
|
|
7
|
-
import { copyDocumentToLocale, deleteDocument, duplicateCollectionDocument, unpublishDocument, updateCollectionDocumentWithPatches, updateDocumentStatus } from "../../server-fns/collections/index.js";
|
|
7
|
+
import { copyDocumentToLocale, deleteDocument, deleteDocumentLocale, duplicateCollectionDocument, unpublishDocument, updateCollectionDocumentWithPatches, updateDocumentStatus } from "../../server-fns/collections/index.js";
|
|
8
8
|
import { useNavigate } from "../chrome/loose-router.js";
|
|
9
9
|
import { useTanStackNavigationGuard } from "./tanstack-navigation-guard.js";
|
|
10
10
|
import { ViewMenu } from "./view-menu.js";
|
|
@@ -290,6 +290,69 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
|
|
|
290
290
|
});
|
|
291
291
|
}
|
|
292
292
|
};
|
|
293
|
+
const handleDeleteLocale = async ({ targetLocale })=>{
|
|
294
|
+
try {
|
|
295
|
+
const result = await deleteDocumentLocale({
|
|
296
|
+
data: {
|
|
297
|
+
collection: path,
|
|
298
|
+
id: String(initialData.id),
|
|
299
|
+
locale: targetLocale
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
const targetLabel = contentLocales.find((l)=>l.code === result.locale)?.label ?? result.locale;
|
|
303
|
+
const description = t("collections.edit.deletedLocaleDescription", {
|
|
304
|
+
label: singular,
|
|
305
|
+
locale: targetLabel
|
|
306
|
+
});
|
|
307
|
+
toastManager.add({
|
|
308
|
+
title: t('collections.edit.deleteLocaleTitle', {
|
|
309
|
+
label: singular
|
|
310
|
+
}),
|
|
311
|
+
description,
|
|
312
|
+
data: {
|
|
313
|
+
intent: 'success',
|
|
314
|
+
iconType: 'success',
|
|
315
|
+
icon: true,
|
|
316
|
+
close: true
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
setEditState({
|
|
320
|
+
status: 'success',
|
|
321
|
+
message: description
|
|
322
|
+
});
|
|
323
|
+
navigate({
|
|
324
|
+
to: '/admin/collections/$collection/$id',
|
|
325
|
+
params: {
|
|
326
|
+
collection: path,
|
|
327
|
+
id: String(initialData.id)
|
|
328
|
+
},
|
|
329
|
+
search: {
|
|
330
|
+
locale: defaultContentLocale
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
} catch (err) {
|
|
334
|
+
console.error('Delete locale error:', err);
|
|
335
|
+
const description = t("collections.edit.deleteLocaleFailedDescription", {
|
|
336
|
+
message: err.message
|
|
337
|
+
});
|
|
338
|
+
toastManager.add({
|
|
339
|
+
title: t('collections.edit.deleteLocaleTitle', {
|
|
340
|
+
label: singular
|
|
341
|
+
}),
|
|
342
|
+
description,
|
|
343
|
+
data: {
|
|
344
|
+
intent: 'danger',
|
|
345
|
+
iconType: 'danger',
|
|
346
|
+
icon: true,
|
|
347
|
+
close: true
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
setEditState({
|
|
351
|
+
status: 'failed',
|
|
352
|
+
message: description
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
};
|
|
293
356
|
const handleDelete = async ()=>{
|
|
294
357
|
try {
|
|
295
358
|
await deleteDocument({
|
|
@@ -445,6 +508,7 @@ const EditView = ({ collectionDefinition, adminConfig, initialData, locale, cont
|
|
|
445
508
|
onDelete: handleDelete,
|
|
446
509
|
onDuplicate: handleDuplicate,
|
|
447
510
|
onCopyToLocale: handleCopyToLocale,
|
|
511
|
+
onDeleteLocale: handleDeleteLocale,
|
|
448
512
|
contentLocales: contentLocales,
|
|
449
513
|
publishedVersion: publishedVersion,
|
|
450
514
|
restoreWarnings: restoreWarnings,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import type { DeleteLocaleResult } from '@byline/core/services';
|
|
9
|
+
/**
|
|
10
|
+
* Remove a single (non-default) content locale from a document, leaving every
|
|
11
|
+
* other locale untouched. Mirrors the thin-wrapper pattern of the other
|
|
12
|
+
* collection server fns: resolve the request context, build the lifecycle
|
|
13
|
+
* context, delegate to the `deleteLocale` service.
|
|
14
|
+
*
|
|
15
|
+
* `assertActorCanPerform('update')` and the default-locale guard run inside
|
|
16
|
+
* the service; auth and validation failures propagate to TanStack Start's
|
|
17
|
+
* transport layer.
|
|
18
|
+
*/
|
|
19
|
+
export declare const deleteDocumentLocale: import("@tanstack/react-start").RequiredFetcher<undefined, (input: {
|
|
20
|
+
collection: string;
|
|
21
|
+
id: string;
|
|
22
|
+
locale: string;
|
|
23
|
+
}) => {
|
|
24
|
+
collection: string;
|
|
25
|
+
id: string;
|
|
26
|
+
locale: string;
|
|
27
|
+
}, Promise<DeleteLocaleResult>>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
2
|
+
import { ERR_NOT_FOUND, getLogger, getServerConfig } from "@byline/core";
|
|
3
|
+
import { deleteLocale } from "@byline/core/services";
|
|
4
|
+
import { getAdminRequestContext } from "../../auth/auth-context.js";
|
|
5
|
+
import { ensureCollection } from "../../integrations/api-utils.js";
|
|
6
|
+
const deleteDocumentLocale = createServerFn({
|
|
7
|
+
method: 'POST'
|
|
8
|
+
}).inputValidator((input)=>input).handler(async ({ data: input })=>{
|
|
9
|
+
const { collection: path, id, locale } = input;
|
|
10
|
+
const logger = getLogger();
|
|
11
|
+
const config = await ensureCollection(path);
|
|
12
|
+
if (!config) throw ERR_NOT_FOUND({
|
|
13
|
+
message: 'Collection not found',
|
|
14
|
+
details: {
|
|
15
|
+
collectionPath: path
|
|
16
|
+
}
|
|
17
|
+
}).log(logger);
|
|
18
|
+
const serverConfig = getServerConfig();
|
|
19
|
+
const ctx = {
|
|
20
|
+
db: serverConfig.db,
|
|
21
|
+
definition: config.definition,
|
|
22
|
+
collectionId: config.collection.id,
|
|
23
|
+
collectionVersion: config.collection.version,
|
|
24
|
+
collectionPath: path,
|
|
25
|
+
logger,
|
|
26
|
+
defaultLocale: serverConfig.i18n.content.defaultLocale,
|
|
27
|
+
slugifier: serverConfig.slugifier,
|
|
28
|
+
requestContext: await getAdminRequestContext()
|
|
29
|
+
};
|
|
30
|
+
return deleteLocale(ctx, {
|
|
31
|
+
documentId: id,
|
|
32
|
+
locale
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
export { deleteDocumentLocale };
|
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.0.
|
|
6
|
+
"version": "3.0.2",
|
|
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/auth": "3.0.
|
|
120
|
-
"@byline/admin": "3.0.
|
|
121
|
-
"@byline/
|
|
122
|
-
"@byline/
|
|
123
|
-
"@byline/
|
|
124
|
-
"@byline/
|
|
118
|
+
"@byline/core": "3.0.2",
|
|
119
|
+
"@byline/auth": "3.0.2",
|
|
120
|
+
"@byline/admin": "3.0.2",
|
|
121
|
+
"@byline/ui": "3.0.2",
|
|
122
|
+
"@byline/ai": "3.0.2",
|
|
123
|
+
"@byline/client": "3.0.2",
|
|
124
|
+
"@byline/i18n": "3.0.2"
|
|
125
125
|
},
|
|
126
126
|
"peerDependencies": {
|
|
127
127
|
"@tanstack/react-router": "^1.167.0",
|
|
@@ -18,6 +18,7 @@ import { Container, Section, useToastManager } from '@byline/ui/react'
|
|
|
18
18
|
import {
|
|
19
19
|
copyDocumentToLocale,
|
|
20
20
|
deleteDocument,
|
|
21
|
+
deleteDocumentLocale,
|
|
21
22
|
duplicateCollectionDocument,
|
|
22
23
|
unpublishDocument,
|
|
23
24
|
updateCollectionDocumentWithPatches,
|
|
@@ -291,6 +292,58 @@ export const EditView = ({
|
|
|
291
292
|
}
|
|
292
293
|
}
|
|
293
294
|
|
|
295
|
+
const handleDeleteLocale = async ({ targetLocale }: { targetLocale: string }) => {
|
|
296
|
+
try {
|
|
297
|
+
const result = await deleteDocumentLocale({
|
|
298
|
+
data: {
|
|
299
|
+
collection: path,
|
|
300
|
+
id: String(initialData.id),
|
|
301
|
+
locale: targetLocale,
|
|
302
|
+
},
|
|
303
|
+
})
|
|
304
|
+
const targetLabel =
|
|
305
|
+
contentLocales.find((l) => l.code === result.locale)?.label ?? result.locale
|
|
306
|
+
const description = t('collections.edit.deletedLocaleDescription', {
|
|
307
|
+
label: singular,
|
|
308
|
+
locale: targetLabel,
|
|
309
|
+
})
|
|
310
|
+
toastManager.add({
|
|
311
|
+
title: t('collections.edit.deleteLocaleTitle', { label: singular }),
|
|
312
|
+
description,
|
|
313
|
+
data: {
|
|
314
|
+
intent: 'success',
|
|
315
|
+
iconType: 'success',
|
|
316
|
+
icon: true,
|
|
317
|
+
close: true,
|
|
318
|
+
},
|
|
319
|
+
})
|
|
320
|
+
setEditState({ status: 'success', message: description })
|
|
321
|
+
// The deleted locale may be the one being viewed — land on the default
|
|
322
|
+
// locale (which always survives) so the loader re-fetches a valid view.
|
|
323
|
+
navigate({
|
|
324
|
+
to: '/admin/collections/$collection/$id' as never,
|
|
325
|
+
params: { collection: path, id: String(initialData.id) },
|
|
326
|
+
search: { locale: defaultContentLocale },
|
|
327
|
+
})
|
|
328
|
+
} catch (err) {
|
|
329
|
+
console.error('Delete locale error:', err)
|
|
330
|
+
const description = t('collections.edit.deleteLocaleFailedDescription', {
|
|
331
|
+
message: (err as Error).message,
|
|
332
|
+
})
|
|
333
|
+
toastManager.add({
|
|
334
|
+
title: t('collections.edit.deleteLocaleTitle', { label: singular }),
|
|
335
|
+
description,
|
|
336
|
+
data: {
|
|
337
|
+
intent: 'danger',
|
|
338
|
+
iconType: 'danger',
|
|
339
|
+
icon: true,
|
|
340
|
+
close: true,
|
|
341
|
+
},
|
|
342
|
+
})
|
|
343
|
+
setEditState({ status: 'failed', message: description })
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
294
347
|
const handleDelete = async () => {
|
|
295
348
|
try {
|
|
296
349
|
await deleteDocument({ data: { collection: path, id: String(initialData.id) } })
|
|
@@ -432,6 +485,7 @@ export const EditView = ({
|
|
|
432
485
|
onDelete={handleDelete}
|
|
433
486
|
onDuplicate={handleDuplicate}
|
|
434
487
|
onCopyToLocale={handleCopyToLocale}
|
|
488
|
+
onDeleteLocale={handleDeleteLocale}
|
|
435
489
|
contentLocales={contentLocales}
|
|
436
490
|
publishedVersion={publishedVersion}
|
|
437
491
|
restoreWarnings={restoreWarnings}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
10
|
+
|
|
11
|
+
import { ERR_NOT_FOUND, getLogger, getServerConfig } from '@byline/core'
|
|
12
|
+
import type { DeleteLocaleResult, DocumentLifecycleContext } from '@byline/core/services'
|
|
13
|
+
import { deleteLocale } from '@byline/core/services'
|
|
14
|
+
|
|
15
|
+
import { getAdminRequestContext } from '../../auth/auth-context.js'
|
|
16
|
+
import { ensureCollection } from '../../integrations/api-utils.js'
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Delete one content locale's data from a document
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Remove a single (non-default) content locale from a document, leaving every
|
|
24
|
+
* other locale untouched. Mirrors the thin-wrapper pattern of the other
|
|
25
|
+
* collection server fns: resolve the request context, build the lifecycle
|
|
26
|
+
* context, delegate to the `deleteLocale` service.
|
|
27
|
+
*
|
|
28
|
+
* `assertActorCanPerform('update')` and the default-locale guard run inside
|
|
29
|
+
* the service; auth and validation failures propagate to TanStack Start's
|
|
30
|
+
* transport layer.
|
|
31
|
+
*/
|
|
32
|
+
export const deleteDocumentLocale = createServerFn({ method: 'POST' })
|
|
33
|
+
.inputValidator((input: { collection: string; id: string; locale: string }) => input)
|
|
34
|
+
.handler(async ({ data: input }): Promise<DeleteLocaleResult> => {
|
|
35
|
+
const { collection: path, id, locale } = input
|
|
36
|
+
const logger = getLogger()
|
|
37
|
+
const config = await ensureCollection(path)
|
|
38
|
+
if (!config) {
|
|
39
|
+
throw ERR_NOT_FOUND({
|
|
40
|
+
message: 'Collection not found',
|
|
41
|
+
details: { collectionPath: path },
|
|
42
|
+
}).log(logger)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const serverConfig = getServerConfig()
|
|
46
|
+
const ctx: DocumentLifecycleContext = {
|
|
47
|
+
db: serverConfig.db,
|
|
48
|
+
definition: config.definition,
|
|
49
|
+
collectionId: config.collection.id,
|
|
50
|
+
collectionVersion: config.collection.version,
|
|
51
|
+
collectionPath: path,
|
|
52
|
+
logger,
|
|
53
|
+
defaultLocale: serverConfig.i18n.content.defaultLocale,
|
|
54
|
+
slugifier: serverConfig.slugifier,
|
|
55
|
+
requestContext: await getAdminRequestContext(),
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return deleteLocale(ctx, { documentId: id, locale })
|
|
59
|
+
})
|
|
@@ -157,7 +157,7 @@ const getDocumentFn = createServerFn({ method: 'GET' })
|
|
|
157
157
|
// `availableLocales` — the stored editorial set → initialises the
|
|
158
158
|
// form-context slot / the checked state.
|
|
159
159
|
// `_availableVersionLocales` — the ledger fact → drives each row's intent.
|
|
160
|
-
// See docs/
|
|
160
|
+
// See docs/I18N.md.
|
|
161
161
|
const availableLocales = (serialised as Record<string, any>).availableLocales as
|
|
162
162
|
| string[]
|
|
163
163
|
| undefined
|