@byline/host-tanstack-start 4.16.0 → 4.18.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/chrome/admin-menu-drawer.js +14 -14
- package/dist/admin-shell/chrome/dashboard.js +41 -5
- package/dist/admin-shell/chrome/dashboard.test.d.ts +8 -0
- package/dist/admin-shell/chrome/router-pager.d.ts +7 -0
- package/dist/admin-shell/chrome/router-pager.js +13 -0
- package/dist/admin-shell/chrome/scroll-to-top.d.ts +20 -0
- package/dist/admin-shell/chrome/scroll-to-top.js +9 -0
- package/dist/admin-shell/collections/api.d.ts +2 -2
- package/dist/admin-shell/collections/create.d.ts +2 -2
- package/dist/admin-shell/collections/create.js +1 -0
- package/dist/admin-shell/collections/edit.d.ts +2 -2
- package/dist/admin-shell/collections/edit.js +1 -0
- package/dist/admin-shell/collections/history.d.ts +4 -12
- package/dist/admin-shell/collections/history.js +112 -303
- package/dist/admin-shell/collections/reindex-button.d.ts +1 -1
- package/dist/admin-shell/collections/reindex-button.js +5 -1
- package/dist/admin-shell/collections/restore-version-modal.d.ts +4 -4
- package/dist/admin-shell/collections/restore-version-modal.js +8 -24
- package/dist/admin-shell/collections/version-history.d.ts +72 -0
- package/dist/admin-shell/collections/version-history.js +259 -0
- package/dist/admin-shell/singletons/history.d.ts +19 -0
- package/dist/admin-shell/singletons/history.js +170 -0
- package/dist/admin-shell/singletons/history.test.d.ts +8 -0
- package/dist/admin-shell/singletons/preview-link.d.ts +12 -0
- package/dist/admin-shell/singletons/preview-link.js +54 -0
- package/dist/admin-shell/singletons/view-menu.d.ts +13 -0
- package/dist/admin-shell/singletons/view-menu.js +116 -0
- package/dist/admin-shell/singletons/view.d.ts +18 -0
- package/dist/admin-shell/singletons/view.js +259 -0
- package/dist/admin-shell/singletons/view.test.d.ts +8 -0
- package/dist/integrations/api-utils.d.ts +18 -4
- package/dist/integrations/api-utils.js +10 -3
- package/dist/routes/create-admin-dashboard-route.js +2 -2
- package/dist/routes/create-collection-api-route.js +3 -3
- package/dist/routes/create-collection-create-route.js +4 -3
- package/dist/routes/create-collection-edit-route.js +4 -3
- package/dist/routes/create-collection-history-route.js +4 -3
- package/dist/routes/create-collection-list-route.js +4 -3
- package/dist/routes/create-singleton-history-route.d.ts +8 -0
- package/dist/routes/create-singleton-history-route.js +99 -0
- package/dist/routes/create-singleton-route.d.ts +35 -0
- package/dist/routes/create-singleton-route.js +130 -0
- package/dist/routes/get-multi-collection-definition.d.ts +10 -0
- package/dist/routes/get-multi-collection-definition.js +6 -0
- package/dist/routes/get-singleton-definition.d.ts +10 -0
- package/dist/routes/get-singleton-definition.js +6 -0
- package/dist/routes/index.d.ts +2 -0
- package/dist/routes/index.js +2 -0
- package/dist/server-fns/actors.d.ts +16 -0
- package/dist/server-fns/actors.js +25 -0
- package/dist/server-fns/admin-document-presentation.d.ts +30 -0
- package/dist/server-fns/admin-document-presentation.js +32 -0
- package/dist/server-fns/collections/actors.d.ts +1 -10
- package/dist/server-fns/collections/actors.js +1 -25
- package/dist/server-fns/collections/get.js +9 -26
- package/dist/server-fns/collections/reorder.js +1 -1
- package/dist/server-fns/collections/scheduled-publication.js +2 -2
- package/dist/server-fns/collections/upload.js +3 -3
- package/dist/server-fns/collections/utils.d.ts +1 -7
- package/dist/server-fns/collections/utils.js +1 -4
- package/dist/server-fns/serialise.d.ts +14 -0
- package/dist/server-fns/serialise.js +4 -0
- package/dist/server-fns/singleton-document-read.d.ts +20 -0
- package/dist/server-fns/singleton-document-read.js +10 -0
- package/dist/server-fns/singletons/cancel-scheduled-publish.d.ts +12 -0
- package/dist/server-fns/singletons/cancel-scheduled-publish.js +7 -0
- package/dist/server-fns/singletons/change-status.d.ts +14 -0
- package/dist/server-fns/singletons/change-status.js +7 -0
- package/dist/server-fns/singletons/confirm-scheduled-publish.d.ts +14 -0
- package/dist/server-fns/singletons/confirm-scheduled-publish.js +9 -0
- package/dist/server-fns/singletons/copy-to-locale.d.ts +18 -0
- package/dist/server-fns/singletons/copy-to-locale.js +11 -0
- package/dist/server-fns/singletons/find-by-version.d.ts +16 -0
- package/dist/server-fns/singletons/find-by-version.js +9 -0
- package/dist/server-fns/singletons/get-scheduled-publish.d.ts +12 -0
- package/dist/server-fns/singletons/get-scheduled-publish.js +7 -0
- package/dist/server-fns/singletons/get.d.ts +24 -0
- package/dist/server-fns/singletons/get.js +6 -0
- package/dist/server-fns/singletons/history.d.ts +31 -0
- package/dist/server-fns/singletons/history.js +22 -0
- package/dist/server-fns/singletons/index.d.ts +19 -0
- package/dist/server-fns/singletons/index.js +12 -0
- package/dist/server-fns/singletons/restore-version.d.ts +14 -0
- package/dist/server-fns/singletons/restore-version.js +7 -0
- package/dist/server-fns/singletons/schedule-publish.d.ts +16 -0
- package/dist/server-fns/singletons/schedule-publish.js +10 -0
- package/dist/server-fns/singletons/unpublish.d.ts +12 -0
- package/dist/server-fns/singletons/unpublish.js +7 -0
- package/dist/server-fns/singletons/update.d.ts +14 -0
- package/dist/server-fns/singletons/update.js +14 -0
- package/dist/vitest-jsdom.test.d.ts +8 -0
- package/package.json +24 -18
- package/src/admin-shell/chrome/admin-menu-drawer.tsx +13 -13
- package/src/admin-shell/chrome/dashboard.test.tsx +199 -0
- package/src/admin-shell/chrome/dashboard.tsx +43 -9
- package/src/admin-shell/chrome/router-pager.tsx +22 -0
- package/src/admin-shell/chrome/scroll-to-top.test.ts +56 -0
- package/src/admin-shell/chrome/scroll-to-top.ts +28 -0
- package/src/admin-shell/collections/api.tsx +2 -2
- package/src/admin-shell/collections/create.tsx +6 -2
- package/src/admin-shell/collections/edit.tsx +6 -2
- package/src/admin-shell/collections/history.module.css +1 -1
- package/src/admin-shell/collections/history.tsx +162 -442
- package/src/admin-shell/collections/reindex-button.tsx +4 -2
- package/src/admin-shell/collections/restore-version-modal.tsx +19 -25
- package/src/admin-shell/collections/version-history.tsx +349 -0
- package/src/admin-shell/singletons/history.test.tsx +407 -0
- package/src/admin-shell/singletons/history.tsx +185 -0
- package/src/admin-shell/singletons/preview-link.tsx +75 -0
- package/src/admin-shell/singletons/view-menu.tsx +136 -0
- package/src/admin-shell/singletons/view.test.tsx +400 -0
- package/src/admin-shell/singletons/view.tsx +351 -0
- package/src/integrations/api-utils.ts +34 -9
- package/src/routes/create-admin-dashboard-route.test.node.ts +70 -0
- package/src/routes/create-admin-dashboard-route.tsx +10 -2
- package/src/routes/create-collection-api-route.tsx +4 -4
- package/src/routes/create-collection-create-route.tsx +5 -8
- package/src/routes/create-collection-edit-route.tsx +5 -4
- package/src/routes/create-collection-history-route.tsx +5 -8
- package/src/routes/create-collection-list-route.tsx +5 -8
- package/src/routes/create-singleton-history-route.test.node.ts +148 -0
- package/src/routes/create-singleton-history-route.tsx +116 -0
- package/src/routes/create-singleton-route.test.node.ts +172 -0
- package/src/routes/create-singleton-route.tsx +176 -0
- package/src/routes/get-multi-collection-definition.ts +16 -0
- package/src/routes/get-singleton-definition.ts +16 -0
- package/src/routes/index.ts +2 -0
- package/src/server-fns/actors.ts +43 -0
- package/src/server-fns/admin-document-presentation.ts +78 -0
- package/src/server-fns/collections/actors.ts +1 -52
- package/src/server-fns/collections/get.ts +10 -49
- package/src/server-fns/collections/reorder.ts +1 -1
- package/src/server-fns/collections/scheduled-publication.ts +7 -1
- package/src/server-fns/collections/upload-singleton.test.node.ts +164 -0
- package/src/server-fns/collections/upload.ts +7 -3
- package/src/server-fns/collections/utils.ts +1 -9
- package/src/server-fns/serialise.ts +17 -0
- package/src/server-fns/singleton-document-read.ts +32 -0
- package/src/server-fns/singletons/cancel-scheduled-publish.ts +19 -0
- package/src/server-fns/singletons/change-status.ts +19 -0
- package/src/server-fns/singletons/confirm-scheduled-publish.ts +23 -0
- package/src/server-fns/singletons/copy-to-locale.ts +32 -0
- package/src/server-fns/singletons/find-by-version.ts +23 -0
- package/src/server-fns/singletons/get-scheduled-publish.ts +19 -0
- package/src/server-fns/singletons/get.ts +32 -0
- package/src/server-fns/singletons/history.ts +41 -0
- package/src/server-fns/singletons/index.ts +20 -0
- package/src/server-fns/singletons/restore-version.ts +19 -0
- package/src/server-fns/singletons/schedule-publish.ts +24 -0
- package/src/server-fns/singletons/singletons.test.node.ts +298 -0
- package/src/server-fns/singletons/unpublish.ts +19 -0
- package/src/server-fns/singletons/update.ts +31 -0
- package/src/vitest-jsdom.test.tsx +27 -0
|
@@ -0,0 +1,8 @@
|
|
|
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
|
+
export declare function createSingletonHistoryRoute(path: string): any;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createFileRoute, notFound } from "@tanstack/react-router";
|
|
3
|
+
import { getSingletonAdminConfig, getWorkflowStatuses } from "@byline/core";
|
|
4
|
+
import { useTranslation } from "@byline/i18n/react";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { BreadcrumbsClient } from "../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js";
|
|
7
|
+
import { SingletonHistoryView } from "../admin-shell/singletons/history.js";
|
|
8
|
+
import { getSingleton, getSingletonHistory } from "../server-fns/singletons/index.js";
|
|
9
|
+
import { getAdminRoutePath } from "./admin-path.js";
|
|
10
|
+
import { getContentLocaleRouteConfig } from "./get-content-locale-route-config.js";
|
|
11
|
+
import { getSingletonDefinition } from "./get-singleton-definition.js";
|
|
12
|
+
const searchSchema = z.object({
|
|
13
|
+
page: z.coerce.number().min(1).optional(),
|
|
14
|
+
page_size: z.coerce.number().max(100).optional(),
|
|
15
|
+
order: z.string().optional(),
|
|
16
|
+
desc: z.coerce.boolean().optional(),
|
|
17
|
+
locale: z.string().optional()
|
|
18
|
+
});
|
|
19
|
+
function createSingletonHistoryRoute(path) {
|
|
20
|
+
const Route = createFileRoute(path)({
|
|
21
|
+
validateSearch: searchSchema,
|
|
22
|
+
loaderDeps: ({ search })=>({
|
|
23
|
+
page: search.page,
|
|
24
|
+
page_size: search.page_size,
|
|
25
|
+
order: search.order,
|
|
26
|
+
desc: search.desc,
|
|
27
|
+
locale: search.locale
|
|
28
|
+
}),
|
|
29
|
+
loader: async ({ params, deps })=>{
|
|
30
|
+
if (null == getSingletonDefinition(params.singleton)) throw notFound();
|
|
31
|
+
const [history, currentDocument] = await Promise.all([
|
|
32
|
+
getSingletonHistory({
|
|
33
|
+
data: {
|
|
34
|
+
singleton: params.singleton,
|
|
35
|
+
params: {
|
|
36
|
+
page: deps.page,
|
|
37
|
+
page_size: deps.page_size,
|
|
38
|
+
order: deps.order,
|
|
39
|
+
desc: deps.desc,
|
|
40
|
+
locale: deps.locale
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}),
|
|
44
|
+
getSingleton({
|
|
45
|
+
data: {
|
|
46
|
+
singleton: params.singleton,
|
|
47
|
+
locale: deps.locale ?? 'all'
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
]);
|
|
51
|
+
return {
|
|
52
|
+
history,
|
|
53
|
+
currentDocument
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
staleTime: 0,
|
|
57
|
+
gcTime: 0,
|
|
58
|
+
shouldReload: true,
|
|
59
|
+
component: function() {
|
|
60
|
+
const { history, currentDocument } = Route.useLoaderData();
|
|
61
|
+
const { singleton } = Route.useParams();
|
|
62
|
+
const definition = getSingletonDefinition(singleton);
|
|
63
|
+
if (null == definition) throw notFound();
|
|
64
|
+
const { t } = useTranslation('byline-admin');
|
|
65
|
+
const { contentLocales, defaultContentLocale } = getContentLocaleRouteConfig();
|
|
66
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
67
|
+
children: [
|
|
68
|
+
/*#__PURE__*/ jsx(BreadcrumbsClient, {
|
|
69
|
+
breadcrumbs: [
|
|
70
|
+
{
|
|
71
|
+
label: t('chrome.menu.dashboard'),
|
|
72
|
+
href: getAdminRoutePath()
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
label: definition.label,
|
|
76
|
+
href: getAdminRoutePath('singletons', singleton)
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
label: t('collections.breadcrumbs.history'),
|
|
80
|
+
href: getAdminRoutePath('singletons', singleton, 'history')
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}),
|
|
84
|
+
/*#__PURE__*/ jsx(SingletonHistoryView, {
|
|
85
|
+
singletonDefinition: definition,
|
|
86
|
+
adminConfig: getSingletonAdminConfig(singleton) ?? void 0,
|
|
87
|
+
data: history,
|
|
88
|
+
currentDocument: currentDocument,
|
|
89
|
+
contentLocales: contentLocales,
|
|
90
|
+
defaultContentLocale: defaultContentLocale,
|
|
91
|
+
workflowStatuses: getWorkflowStatuses(definition)
|
|
92
|
+
})
|
|
93
|
+
]
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
return Route;
|
|
98
|
+
}
|
|
99
|
+
export { createSingletonHistoryRoute };
|
|
@@ -0,0 +1,35 @@
|
|
|
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 { DocumentPublishScheduleInfo } from '@byline/client';
|
|
9
|
+
/**
|
|
10
|
+
* Load the mapped singleton document and attach the admin-only lifecycle
|
|
11
|
+
* metadata consumed by the editor. Keeping this composition in the route
|
|
12
|
+
* layer leaves ordinary singleton reads free of publication timing and actor
|
|
13
|
+
* capability details.
|
|
14
|
+
*/
|
|
15
|
+
export declare const getSingletonRouteDocument: import("@tanstack/react-start").RequiredFetcher<undefined, (input: {
|
|
16
|
+
singleton: string;
|
|
17
|
+
locale?: string;
|
|
18
|
+
}) => {
|
|
19
|
+
singleton: string;
|
|
20
|
+
locale?: string;
|
|
21
|
+
}, Promise<{
|
|
22
|
+
document: null;
|
|
23
|
+
initialData: Record<string, any>;
|
|
24
|
+
} | {
|
|
25
|
+
document: {
|
|
26
|
+
_publishedVersion: Record<string, any> | null;
|
|
27
|
+
_scheduledPublicationEnabled: boolean;
|
|
28
|
+
_canSchedulePublication: boolean;
|
|
29
|
+
_scheduledPublish: DocumentPublishScheduleInfo | null;
|
|
30
|
+
scheduledPublishAt?: Date | undefined;
|
|
31
|
+
scheduledPublishVersionId?: string | undefined;
|
|
32
|
+
};
|
|
33
|
+
initialData: undefined;
|
|
34
|
+
} | null>>;
|
|
35
|
+
export declare function createSingletonRoute(path: string): any;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createFileRoute, notFound } from "@tanstack/react-router";
|
|
3
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
4
|
+
import { getAdminBylineClient, getAdminRequestContext } from "@byline/client/server";
|
|
5
|
+
import { buildInitialDataFromFields, documentAbilityKey, getServerConfig, getSingletonAdminConfig } from "@byline/core";
|
|
6
|
+
import { useTranslation } from "@byline/i18n/react";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { BreadcrumbsClient } from "../admin-shell/chrome/breadcrumbs/breadcrumbs-client.js";
|
|
9
|
+
import { SingletonView } from "../admin-shell/singletons/view.js";
|
|
10
|
+
import { bylineCore } from "../integrations/byline-core.js";
|
|
11
|
+
import { serialise } from "../server-fns/serialise.js";
|
|
12
|
+
import { readSingletonDocument } from "../server-fns/singleton-document-read.js";
|
|
13
|
+
import { getAdminRoutePath } from "./admin-path.js";
|
|
14
|
+
import { getContentLocaleRouteConfig } from "./get-content-locale-route-config.js";
|
|
15
|
+
import { getSingletonDefinition } from "./get-singleton-definition.js";
|
|
16
|
+
const searchSchema = z.object({
|
|
17
|
+
locale: z.string().optional()
|
|
18
|
+
});
|
|
19
|
+
const getSingletonRouteDocument = createServerFn({
|
|
20
|
+
method: 'GET'
|
|
21
|
+
}).validator((input)=>input).handler(async ({ data })=>{
|
|
22
|
+
const definition = getSingletonDefinition(data.singleton);
|
|
23
|
+
if (null == definition) return null;
|
|
24
|
+
const document = await readSingletonDocument({
|
|
25
|
+
singleton: data.singleton,
|
|
26
|
+
locale: data.locale,
|
|
27
|
+
populateRelations: true
|
|
28
|
+
});
|
|
29
|
+
if (null == document) return {
|
|
30
|
+
document: null,
|
|
31
|
+
initialData: serialise(await buildInitialDataFromFields(definition.fields, {
|
|
32
|
+
locale: data.locale ?? getServerConfig().i18n.content.defaultLocale
|
|
33
|
+
}))
|
|
34
|
+
};
|
|
35
|
+
const config = getServerConfig();
|
|
36
|
+
const record = bylineCore().getCollectionRecord(data.singleton);
|
|
37
|
+
let publishedVersion = null;
|
|
38
|
+
if ('published' !== document.status) {
|
|
39
|
+
const published = await config.db.queries.documents.getPublishedVersion({
|
|
40
|
+
collection_id: record.collectionId,
|
|
41
|
+
document_id: String(document.id)
|
|
42
|
+
});
|
|
43
|
+
publishedVersion = published ? serialise({
|
|
44
|
+
id: published.document_id,
|
|
45
|
+
versionId: published.document_version_id,
|
|
46
|
+
status: published.status,
|
|
47
|
+
createdAt: published.created_at,
|
|
48
|
+
updatedAt: published.updated_at
|
|
49
|
+
}) : null;
|
|
50
|
+
}
|
|
51
|
+
const scheduledPublicationEnabled = config.scheduledPublication?.enabled === true;
|
|
52
|
+
let canSchedulePublication = false;
|
|
53
|
+
let scheduledPublish = null;
|
|
54
|
+
if (scheduledPublicationEnabled) {
|
|
55
|
+
const actor = (await getAdminRequestContext()).actor;
|
|
56
|
+
canSchedulePublication = actor?.hasAbility(documentAbilityKey(definition, 'changeStatus')) === true && actor.hasAbility(documentAbilityKey(definition, 'publish'));
|
|
57
|
+
if (canSchedulePublication) scheduledPublish = await getAdminBylineClient().singleton(data.singleton).getScheduledPublish();
|
|
58
|
+
}
|
|
59
|
+
const serializedSchedule = null == scheduledPublish ? null : serialise(scheduledPublish);
|
|
60
|
+
return {
|
|
61
|
+
document: {
|
|
62
|
+
...document,
|
|
63
|
+
_publishedVersion: publishedVersion,
|
|
64
|
+
_scheduledPublicationEnabled: scheduledPublicationEnabled,
|
|
65
|
+
_canSchedulePublication: canSchedulePublication,
|
|
66
|
+
_scheduledPublish: serializedSchedule,
|
|
67
|
+
...null == serializedSchedule ? {} : {
|
|
68
|
+
scheduledPublishAt: serializedSchedule.publishAt,
|
|
69
|
+
scheduledPublishVersionId: serializedSchedule.targetVersionId
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
initialData: void 0
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
function createSingletonRoute(path) {
|
|
76
|
+
const Route = createFileRoute(path)({
|
|
77
|
+
validateSearch: searchSchema,
|
|
78
|
+
loaderDeps: ({ search })=>({
|
|
79
|
+
locale: search.locale
|
|
80
|
+
}),
|
|
81
|
+
loader: async ({ params, deps })=>{
|
|
82
|
+
if (null == getSingletonDefinition(params.singleton)) throw notFound();
|
|
83
|
+
return getSingletonRouteDocument({
|
|
84
|
+
data: {
|
|
85
|
+
singleton: params.singleton,
|
|
86
|
+
locale: deps.locale
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
staleTime: 0,
|
|
91
|
+
gcTime: 0,
|
|
92
|
+
shouldReload: true,
|
|
93
|
+
component: function() {
|
|
94
|
+
const routeState = Route.useLoaderData();
|
|
95
|
+
const { singleton } = Route.useParams();
|
|
96
|
+
const { locale } = Route.useSearch();
|
|
97
|
+
const definition = getSingletonDefinition(singleton);
|
|
98
|
+
if (null == definition) throw notFound();
|
|
99
|
+
const { t } = useTranslation('byline-admin');
|
|
100
|
+
const { contentLocales, defaultContentLocale } = getContentLocaleRouteConfig();
|
|
101
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
102
|
+
children: [
|
|
103
|
+
/*#__PURE__*/ jsx(BreadcrumbsClient, {
|
|
104
|
+
breadcrumbs: [
|
|
105
|
+
{
|
|
106
|
+
label: t('chrome.menu.dashboard'),
|
|
107
|
+
href: getAdminRoutePath()
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
label: definition.label,
|
|
111
|
+
href: getAdminRoutePath('singletons', singleton)
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
}),
|
|
115
|
+
/*#__PURE__*/ jsx(SingletonView, {
|
|
116
|
+
singletonDefinition: definition,
|
|
117
|
+
adminConfig: getSingletonAdminConfig(singleton) ?? void 0,
|
|
118
|
+
document: routeState.document,
|
|
119
|
+
initialData: routeState.initialData,
|
|
120
|
+
locale: locale,
|
|
121
|
+
contentLocales: contentLocales,
|
|
122
|
+
defaultContentLocale: defaultContentLocale
|
|
123
|
+
})
|
|
124
|
+
]
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return Route;
|
|
129
|
+
}
|
|
130
|
+
export { createSingletonRoute, getSingletonRouteDocument };
|
|
@@ -0,0 +1,10 @@
|
|
|
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 { MultiCollectionDefinition } from '@byline/core';
|
|
9
|
+
/** Resolve only the resource kind supported by the collection route family. */
|
|
10
|
+
export declare function getMultiCollectionDefinition(path: string): MultiCollectionDefinition | null;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { getCollectionDefinition, isSingleton } from "@byline/core";
|
|
2
|
+
function getMultiCollectionDefinition(path) {
|
|
3
|
+
const definition = getCollectionDefinition(path);
|
|
4
|
+
return null == definition || isSingleton(definition) ? null : definition;
|
|
5
|
+
}
|
|
6
|
+
export { getMultiCollectionDefinition };
|
|
@@ -0,0 +1,10 @@
|
|
|
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 { SingletonDefinition } from '@byline/core';
|
|
9
|
+
/** Resolve only the resource kind supported by the singleton route family. */
|
|
10
|
+
export declare function getSingletonDefinition(path: string): SingletonDefinition | null;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { getCollectionDefinition, isSingleton } from "@byline/core";
|
|
2
|
+
function getSingletonDefinition(path) {
|
|
3
|
+
const definition = getCollectionDefinition(path);
|
|
4
|
+
return null != definition && isSingleton(definition) ? definition : null;
|
|
5
|
+
}
|
|
6
|
+
export { getSingletonDefinition };
|
package/dist/routes/index.d.ts
CHANGED
|
@@ -38,3 +38,5 @@ export { createCollectionEditRoute } from './create-collection-edit-route.js';
|
|
|
38
38
|
export { createCollectionHistoryRoute } from './create-collection-history-route.js';
|
|
39
39
|
export { createCollectionListRoute } from './create-collection-list-route.js';
|
|
40
40
|
export { type CreateSignInRouteOptions, createSignInRoute, } from './create-sign-in-route.js';
|
|
41
|
+
export { createSingletonHistoryRoute } from './create-singleton-history-route.js';
|
|
42
|
+
export { createSingletonRoute } from './create-singleton-route.js';
|
package/dist/routes/index.js
CHANGED
|
@@ -17,3 +17,5 @@ export { createCollectionEditRoute } from "./create-collection-edit-route.js";
|
|
|
17
17
|
export { createCollectionHistoryRoute } from "./create-collection-history-route.js";
|
|
18
18
|
export { createCollectionListRoute } from "./create-collection-list-route.js";
|
|
19
19
|
export { createSignInRoute } from "./create-sign-in-route.js";
|
|
20
|
+
export { createSingletonHistoryRoute } from "./create-singleton-history-route.js";
|
|
21
|
+
export { createSingletonRoute } from "./create-singleton-route.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
export type ActorLabelMap = Record<string, {
|
|
9
|
+
label: string;
|
|
10
|
+
}>;
|
|
11
|
+
/**
|
|
12
|
+
* Batch-resolve admin-user ids to display labels. The admin server-fn layer
|
|
13
|
+
* owns this presentation concern so both collection and singleton history
|
|
14
|
+
* can share it without teaching document storage about admin-realm tables.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveActorLabels(ids: Iterable<string | null | undefined>): Promise<ActorLabelMap>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { bylineCore } from "../integrations/byline-core.js";
|
|
2
|
+
function labelFor(row) {
|
|
3
|
+
const name = [
|
|
4
|
+
row.given_name,
|
|
5
|
+
row.family_name
|
|
6
|
+
].filter(Boolean).join(' ');
|
|
7
|
+
return name || row.username || row.email;
|
|
8
|
+
}
|
|
9
|
+
async function resolveActorLabels(ids) {
|
|
10
|
+
const unique = [
|
|
11
|
+
...new Set([
|
|
12
|
+
...ids
|
|
13
|
+
].filter((id)=>'string' == typeof id && id.length > 0))
|
|
14
|
+
];
|
|
15
|
+
if (0 === unique.length) return {};
|
|
16
|
+
const store = bylineCore().adminStore;
|
|
17
|
+
if (null == store) return {};
|
|
18
|
+
const rows = await store.adminUsers.getByIds(unique);
|
|
19
|
+
const map = {};
|
|
20
|
+
for (const row of rows)map[row.id] = {
|
|
21
|
+
label: labelFor(row)
|
|
22
|
+
};
|
|
23
|
+
return map;
|
|
24
|
+
}
|
|
25
|
+
export { resolveActorLabels };
|
|
@@ -0,0 +1,30 @@
|
|
|
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 CollectionDefinition, type PopulateSpec } from '@byline/core';
|
|
9
|
+
export interface AdminDocumentReadInput {
|
|
10
|
+
locale?: string;
|
|
11
|
+
depth?: number;
|
|
12
|
+
populateRelations?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface AdminDocumentReadOptions {
|
|
15
|
+
locale: string;
|
|
16
|
+
populate?: PopulateSpec;
|
|
17
|
+
depth?: number;
|
|
18
|
+
status: 'any';
|
|
19
|
+
onMissingLocale: 'empty';
|
|
20
|
+
lenient: true;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the shared read controls used by collection and singleton editors.
|
|
24
|
+
* Explicit depth is the API-preview mode; otherwise relation-summary mode
|
|
25
|
+
* projects only each target's picker/title fields for first-paint tiles.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveAdminDocumentRead(definition: CollectionDefinition | null, input: AdminDocumentReadInput): {
|
|
28
|
+
options: AdminDocumentReadOptions;
|
|
29
|
+
populatedTree: boolean;
|
|
30
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { buildRelationSummaryPopulateMap, getCollectionAdminConfig, getCollectionDefinition } from "@byline/core";
|
|
2
|
+
function resolveAdminDocumentRead(definition, input) {
|
|
3
|
+
const populateRequested = 'number' == typeof input.depth && input.depth > 0;
|
|
4
|
+
const autoRelationsActive = !populateRequested && true === input.populateRelations;
|
|
5
|
+
let populate;
|
|
6
|
+
let depth;
|
|
7
|
+
if (populateRequested) {
|
|
8
|
+
populate = '*';
|
|
9
|
+
depth = input.depth;
|
|
10
|
+
} else if (autoRelationsActive && null != definition) {
|
|
11
|
+
const populateMap = buildRelationSummaryPopulateMap(definition.fields, (targetPath)=>({
|
|
12
|
+
def: getCollectionDefinition(targetPath),
|
|
13
|
+
admin: getCollectionAdminConfig(targetPath)
|
|
14
|
+
}));
|
|
15
|
+
if (Object.keys(populateMap).length > 0) {
|
|
16
|
+
populate = populateMap;
|
|
17
|
+
depth = 1;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
options: {
|
|
22
|
+
locale: input.locale ?? 'en',
|
|
23
|
+
populate,
|
|
24
|
+
depth,
|
|
25
|
+
status: 'any',
|
|
26
|
+
onMissingLocale: 'empty',
|
|
27
|
+
lenient: true
|
|
28
|
+
},
|
|
29
|
+
populatedTree: populateRequested || autoRelationsActive
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export { resolveAdminDocumentRead };
|
|
@@ -5,13 +5,4 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Copyright (c) Infonomic Company Limited
|
|
7
7
|
*/
|
|
8
|
-
export type ActorLabelMap
|
|
9
|
-
label: string;
|
|
10
|
-
}>;
|
|
11
|
-
/**
|
|
12
|
-
* Batch-resolve admin-user ids to display labels. Accepts the raw
|
|
13
|
-
* `createdBy` values straight off a page of shaped documents — nullish
|
|
14
|
-
* and duplicate entries are tolerated and deduplicated. Returns `{}`
|
|
15
|
-
* when there is nothing to resolve or no admin store is configured.
|
|
16
|
-
*/
|
|
17
|
-
export declare function resolveActorLabels(ids: Iterable<string | null | undefined>): Promise<ActorLabelMap>;
|
|
8
|
+
export { type ActorLabelMap, resolveActorLabels } from '../actors.js';
|
|
@@ -1,25 +1 @@
|
|
|
1
|
-
|
|
2
|
-
function labelFor(row) {
|
|
3
|
-
const name = [
|
|
4
|
-
row.given_name,
|
|
5
|
-
row.family_name
|
|
6
|
-
].filter(Boolean).join(' ');
|
|
7
|
-
return name || row.username || row.email;
|
|
8
|
-
}
|
|
9
|
-
async function resolveActorLabels(ids) {
|
|
10
|
-
const unique = [
|
|
11
|
-
...new Set([
|
|
12
|
-
...ids
|
|
13
|
-
].filter((id)=>'string' == typeof id && id.length > 0))
|
|
14
|
-
];
|
|
15
|
-
if (0 === unique.length) return {};
|
|
16
|
-
const store = bylineCore().adminStore;
|
|
17
|
-
if (null == store) return {};
|
|
18
|
-
const rows = await store.adminUsers.getByIds(unique);
|
|
19
|
-
const map = {};
|
|
20
|
-
for (const row of rows)map[row.id] = {
|
|
21
|
-
label: labelFor(row)
|
|
22
|
-
};
|
|
23
|
-
return map;
|
|
24
|
-
}
|
|
25
|
-
export { resolveActorLabels };
|
|
1
|
+
export { resolveActorLabels } from "../actors.js";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createServerFn } from "@tanstack/react-start";
|
|
2
2
|
import { getAdminBylineClient, getAdminRequestContext } from "@byline/client/server";
|
|
3
|
-
import { BylineError, ERR_NOT_FOUND, ErrorCodes,
|
|
3
|
+
import { BylineError, ERR_NOT_FOUND, ErrorCodes, documentAbilityKey, getCollectionSchemasForPath, getLogger, getServerConfig } from "@byline/core";
|
|
4
4
|
import { ensureCollection } from "../../integrations/api-utils.js";
|
|
5
|
+
import { resolveAdminDocumentRead } from "../admin-document-presentation.js";
|
|
5
6
|
import { serialise } from "./utils.js";
|
|
6
7
|
const getDocumentFn = createServerFn({
|
|
7
8
|
method: 'GET'
|
|
@@ -17,30 +18,13 @@ const getDocumentFn = createServerFn({
|
|
|
17
18
|
}).log(logger);
|
|
18
19
|
const client = getAdminBylineClient();
|
|
19
20
|
const handle = client.collection(path);
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
populate = '*';
|
|
26
|
-
resolvedDepth = depth;
|
|
27
|
-
} else if (autoRelationsActive) {
|
|
28
|
-
const populateMap = buildRelationSummaryPopulateMap(config.definition.fields, (targetPath)=>({
|
|
29
|
-
def: getCollectionDefinition(targetPath),
|
|
30
|
-
admin: getCollectionAdminConfig(targetPath)
|
|
31
|
-
}));
|
|
32
|
-
if (Object.keys(populateMap).length > 0) {
|
|
33
|
-
populate = populateMap;
|
|
34
|
-
resolvedDepth = 1;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
21
|
+
const { options: readOptions, populatedTree } = resolveAdminDocumentRead(config.definition, {
|
|
22
|
+
locale,
|
|
23
|
+
depth,
|
|
24
|
+
populateRelations
|
|
25
|
+
});
|
|
37
26
|
const document = await handle.findById(id, {
|
|
38
|
-
|
|
39
|
-
populate,
|
|
40
|
-
depth: resolvedDepth,
|
|
41
|
-
status: 'any',
|
|
42
|
-
onMissingLocale: 'empty',
|
|
43
|
-
lenient: true
|
|
27
|
+
...readOptions
|
|
44
28
|
});
|
|
45
29
|
if (!document) throw ERR_NOT_FOUND({
|
|
46
30
|
message: 'Document not found',
|
|
@@ -50,7 +34,6 @@ const getDocumentFn = createServerFn({
|
|
|
50
34
|
}
|
|
51
35
|
}).log(logger);
|
|
52
36
|
const serialised = serialise(document);
|
|
53
|
-
const populatedTree = populateRequested || autoRelationsActive;
|
|
54
37
|
const parsed = 'all' === locale || populatedTree ? serialised : (()=>{
|
|
55
38
|
const { get } = getCollectionSchemasForPath(path);
|
|
56
39
|
return get.parse(serialised);
|
|
@@ -77,7 +60,7 @@ const getDocumentFn = createServerFn({
|
|
|
77
60
|
let scheduledPublish = null;
|
|
78
61
|
if (scheduledPublicationEnabled) {
|
|
79
62
|
const actor = (await getAdminRequestContext()).actor;
|
|
80
|
-
canSchedulePublication = actor?.hasAbility(
|
|
63
|
+
canSchedulePublication = actor?.hasAbility(documentAbilityKey(config.definition, 'changeStatus')) === true && actor.hasAbility(documentAbilityKey(config.definition, 'publish'));
|
|
81
64
|
if (canSchedulePublication) scheduledPublish = await handle.getScheduledPublish(id);
|
|
82
65
|
}
|
|
83
66
|
const serializedSchedule = null == scheduledPublish ? null : serialise(scheduledPublish);
|
|
@@ -21,7 +21,7 @@ const reorderCollectionDocument = createServerFn({
|
|
|
21
21
|
}
|
|
22
22
|
}).log(logger);
|
|
23
23
|
const requestContext = await getAdminRequestContext();
|
|
24
|
-
assertActorCanPerform(requestContext,
|
|
24
|
+
assertActorCanPerform(requestContext, config.definition, 'update');
|
|
25
25
|
const serverConfig = getServerConfig();
|
|
26
26
|
const collectionId = config.collection.id;
|
|
27
27
|
const canonical = await serverConfig.db.queries.documents.getCanonicalDocumentOrder({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createServerFn } from "@tanstack/react-start";
|
|
2
2
|
import { getAdminBylineClient, getAdminRequestContext } from "@byline/client/server";
|
|
3
|
-
import { ERR_NOT_FOUND, ERR_VALIDATION } from "@byline/core";
|
|
3
|
+
import { ERR_NOT_FOUND, ERR_VALIDATION, isSingleton } from "@byline/core";
|
|
4
4
|
import { listDocumentPublishSchedules } from "@byline/core/services";
|
|
5
5
|
import { bylineCore } from "../../integrations/byline-core.js";
|
|
6
6
|
import { omitScheduleExecutionState } from "./scheduled-publication-response.js";
|
|
@@ -138,7 +138,7 @@ const listScheduledPublications = createServerFn({
|
|
|
138
138
|
return {
|
|
139
139
|
...serializeSchedule(schedule),
|
|
140
140
|
collectionPath: definition?.path ?? schedule.collectionId,
|
|
141
|
-
collectionLabel: definition
|
|
141
|
+
collectionLabel: null == definition ? schedule.collectionId : isSingleton(definition) ? definition.label : definition.labels.plural,
|
|
142
142
|
documentPath,
|
|
143
143
|
lastAuthorizedByName: null == schedule.lastAuthorizedBy ? null : authorizerNames.get(schedule.lastAuthorizedBy) ?? null
|
|
144
144
|
};
|
|
@@ -4,7 +4,7 @@ import { ERR_NOT_FOUND, ERR_VALIDATION, getServerConfig, getUploadFields } from
|
|
|
4
4
|
import { extractImageMeta, generateImageVariants, isBypassMimeType } from "@byline/core/image";
|
|
5
5
|
import { getLogger, withLogContext } from "@byline/core/logger";
|
|
6
6
|
import { uploadField } from "@byline/core/services";
|
|
7
|
-
import {
|
|
7
|
+
import { ensureDocumentResource } from "../../integrations/api-utils.js";
|
|
8
8
|
function parseUploadFormData(data) {
|
|
9
9
|
if (!(data instanceof FormData)) throw new Error('Expected FormData upload payload.');
|
|
10
10
|
const collectionEntry = data.get('collection');
|
|
@@ -64,9 +64,9 @@ const uploadCollectionField = createServerFn({
|
|
|
64
64
|
module: 'upload',
|
|
65
65
|
function: 'uploadCollectionField'
|
|
66
66
|
}, async ()=>{
|
|
67
|
-
const config = await
|
|
67
|
+
const config = await ensureDocumentResource(collectionPath);
|
|
68
68
|
if (null == config) throw ERR_NOT_FOUND({
|
|
69
|
-
message: '
|
|
69
|
+
message: 'Document resource not found.',
|
|
70
70
|
details: {
|
|
71
71
|
collectionPath
|
|
72
72
|
}
|
|
@@ -5,10 +5,4 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Copyright (c) Infonomic Company Limited
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
* Deep-serialise a value through JSON to convert Date objects to ISO strings.
|
|
10
|
-
* TanStack Start server functions pass return values directly during SSR
|
|
11
|
-
* (no automatic JSON round-trip), so Date instances from the DB driver would
|
|
12
|
-
* fail downstream Zod z.string() checks without this explicit step.
|
|
13
|
-
*/
|
|
14
|
-
export declare function serialise<T>(value: T): T;
|
|
8
|
+
export { serialise } from '../serialise.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
* Deep-serialise a value through JSON to convert Date objects to ISO strings.
|
|
10
|
+
* TanStack Start server functions pass return values directly during SSR
|
|
11
|
+
* (no automatic JSON round-trip), so Date instances from the DB driver would
|
|
12
|
+
* fail downstream string checks without this explicit step.
|
|
13
|
+
*/
|
|
14
|
+
export declare function serialise<T>(value: T): T;
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
export interface SingletonDocumentReadInput {
|
|
9
|
+
singleton: string;
|
|
10
|
+
locale?: string;
|
|
11
|
+
depth?: number;
|
|
12
|
+
populateRelations?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Read the singleton document with the presentation controls shared by the
|
|
16
|
+
* editor route and the public server function. Route-only lifecycle metadata
|
|
17
|
+
* is deliberately composed one layer up, where host database and actor
|
|
18
|
+
* context are available without widening the singleton transport contract.
|
|
19
|
+
*/
|
|
20
|
+
export declare function readSingletonDocument(data: SingletonDocumentReadInput): Promise<import("@byline/client").SingletonDocument<Record<string, any>> | null>;
|