@carlonicora/nextjs-jsonapi 5.3.0 → 5.4.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/{BlockNoteEditor-UJ6363LC.js → BlockNoteEditor-4YCAIEPT.js} +23 -22
- package/dist/BlockNoteEditor-4YCAIEPT.js.map +1 -0
- package/dist/{BlockNoteEditor-WTSQANKI.mjs → BlockNoteEditor-YQL2SGFR.mjs} +8 -7
- package/dist/BlockNoteEditor-YQL2SGFR.mjs.map +1 -0
- package/dist/{BlockNoteViewer-JVKWJZ6J.mjs → BlockNoteViewer-AEJKJ27Q.mjs} +2 -2
- package/dist/{BlockNoteViewer-EL4JFB6P.js → BlockNoteViewer-YL3J7J2Y.js} +3 -3
- package/dist/{BlockNoteViewer-EL4JFB6P.js.map → BlockNoteViewer-YL3J7J2Y.js.map} +1 -1
- package/dist/BlogCategoryFields-DO48vOTE.d.mts +14 -0
- package/dist/BlogCategoryFields-DO48vOTE.d.ts +14 -0
- package/dist/BlogPostInterface-BB_4wcDR.d.mts +124 -0
- package/dist/BlogPostInterface-bWAT1rfR.d.ts +124 -0
- package/dist/billing/index.js +441 -441
- package/dist/billing/index.mjs +3 -3
- package/dist/blog-public.types-BbrzsC1c.d.mts +30 -0
- package/dist/blog-public.types-BbrzsC1c.d.ts +30 -0
- package/dist/{chunk-3BAM23VA.js → chunk-3NLAXVIN.js} +860 -849
- package/dist/chunk-3NLAXVIN.js.map +1 -0
- package/dist/{chunk-QKZUE5OF.mjs → chunk-3YW35YHQ.mjs} +1 -101
- package/dist/chunk-3YW35YHQ.mjs.map +1 -0
- package/dist/{chunk-QQQE3N2X.js → chunk-5PPG6PL7.js} +3 -3
- package/dist/{chunk-QQQE3N2X.js.map → chunk-5PPG6PL7.js.map} +1 -1
- package/dist/{chunk-FNTQQFLH.mjs → chunk-6DC2WVVB.mjs} +2 -2
- package/dist/{chunk-MIZTWBPX.mjs → chunk-EUKTBOI2.mjs} +19 -8
- package/dist/chunk-EUKTBOI2.mjs.map +1 -0
- package/dist/{chunk-XGTQWBDJ.js → chunk-KSYQEKJX.js} +11 -111
- package/dist/chunk-KSYQEKJX.js.map +1 -0
- package/dist/{chunk-CRI4T47Y.js → chunk-NFBOSPNJ.js} +756 -41
- package/dist/chunk-NFBOSPNJ.js.map +1 -0
- package/dist/{chunk-6WU74VFU.mjs → chunk-QMYQRPQC.mjs} +2 -2
- package/dist/{chunk-JQWI62NV.mjs → chunk-WC63PJSC.mjs} +716 -1
- package/dist/chunk-WC63PJSC.mjs.map +1 -0
- package/dist/chunk-XCHSX3VC.mjs +107 -0
- package/dist/chunk-XCHSX3VC.mjs.map +1 -0
- package/dist/{chunk-EO75CV76.js → chunk-YNCQSWQW.js} +8 -8
- package/dist/{chunk-EO75CV76.js.map → chunk-YNCQSWQW.js.map} +1 -1
- package/dist/chunk-YW4ZCEWB.js +107 -0
- package/dist/chunk-YW4ZCEWB.js.map +1 -0
- package/dist/client/index.js +4 -4
- package/dist/client/index.mjs +3 -3
- package/dist/components/index.d.mts +13 -2
- package/dist/components/index.d.ts +13 -2
- package/dist/components/index.js +4 -4
- package/dist/components/index.mjs +3 -3
- package/dist/contexts/index.js +4 -4
- package/dist/contexts/index.mjs +3 -3
- package/dist/core/index.d.mts +214 -3
- package/dist/core/index.d.ts +214 -3
- package/dist/core/index.js +36 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +35 -1
- package/dist/email-automations/index.js +92 -92
- package/dist/email-automations/index.mjs +3 -3
- package/dist/features/analytics/index.js +122 -122
- package/dist/features/analytics/index.mjs +4 -4
- package/dist/features/analytics/server.js +6 -5
- package/dist/features/analytics/server.js.map +1 -1
- package/dist/features/analytics/server.mjs +4 -3
- package/dist/features/analytics/server.mjs.map +1 -1
- package/dist/features/blog/index.css +30 -0
- package/dist/features/blog/index.css.map +1 -0
- package/dist/features/blog/index.d.mts +266 -0
- package/dist/features/blog/index.d.ts +266 -0
- package/dist/features/blog/index.js +1799 -0
- package/dist/features/blog/index.js.map +1 -0
- package/dist/features/blog/index.mjs +1799 -0
- package/dist/features/blog/index.mjs.map +1 -0
- package/dist/features/blog/server.d.mts +33 -0
- package/dist/features/blog/server.d.ts +33 -0
- package/dist/features/blog/server.js +139 -0
- package/dist/features/blog/server.js.map +1 -0
- package/dist/features/blog/server.mjs +139 -0
- package/dist/features/blog/server.mjs.map +1 -0
- package/dist/features/help/index.js +37 -37
- package/dist/features/help/index.mjs +3 -3
- package/dist/features/tokenusage/index.js +125 -125
- package/dist/features/tokenusage/index.mjs +4 -4
- package/dist/index.d.mts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +37 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +36 -2
- package/dist/{s3.service-CY-jgOAM.d.ts → s3.service-Bz_K-tjz.d.ts} +11 -0
- package/dist/{s3.service-Sri0QP7Z.d.mts → s3.service-D5zNCEW3.d.mts} +11 -0
- package/dist/server/index.d.mts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +8 -6
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +12 -10
- package/messages/en.json +93 -0
- package/messages/it.json +93 -0
- package/package.json +11 -1
- package/src/components/editors/BlockNoteEditor.tsx +13 -3
- package/src/components/forms/FormBlockNote.tsx +4 -0
- package/src/components/navigations/ContentTitle.tsx +14 -3
- package/src/core/index.ts +4 -0
- package/src/core/registry/ModuleRegistry.ts +6 -0
- package/src/features/blog/BlogModules.ts +49 -0
- package/src/features/blog/components/admin/BlogAdminContainer.tsx +32 -0
- package/src/features/blog/components/admin/BlogCategoriesList.tsx +56 -0
- package/src/features/blog/components/admin/BlogCategoryEditor.tsx +230 -0
- package/src/features/blog/components/admin/BlogCoverImageField.tsx +123 -0
- package/src/features/blog/components/admin/BlogLayoutSetting.tsx +86 -0
- package/src/features/blog/components/admin/BlogPostComparison.tsx +54 -0
- package/src/features/blog/components/admin/BlogPostContainer.tsx +102 -0
- package/src/features/blog/components/admin/BlogPostDeleter.tsx +35 -0
- package/src/features/blog/components/admin/BlogPostEditor.tsx +207 -0
- package/src/features/blog/components/admin/BlogPostPublishButton.tsx +50 -0
- package/src/features/blog/components/admin/BlogPostTranslationEditor.tsx +110 -0
- package/src/features/blog/components/admin/BlogPostTranslationPanel.tsx +136 -0
- package/src/features/blog/components/admin/BlogPostsList.tsx +58 -0
- package/src/features/blog/components/admin/BlogTranslationStatus.tsx +104 -0
- package/src/features/blog/components/admin/__tests__/BlogPostTranslationPanel.spec.tsx +100 -0
- package/src/features/blog/components/admin/__tests__/BlogPostsList.spec.tsx +30 -0
- package/src/features/blog/components/admin/index.ts +14 -0
- package/src/features/blog/components/public/BlogCategoryChips.tsx +59 -0
- package/src/features/blog/components/public/BlogList.tsx +21 -0
- package/src/features/blog/components/public/BlogListColumn.tsx +53 -0
- package/src/features/blog/components/public/BlogListFeatured.tsx +57 -0
- package/src/features/blog/components/public/BlogListParts.tsx +74 -0
- package/src/features/blog/components/public/BlogListRail.tsx +62 -0
- package/src/features/blog/components/public/BlogPostCard.tsx +132 -0
- package/src/features/blog/components/public/BlogPostMeta.tsx +49 -0
- package/src/features/blog/components/public/BlogPostView.tsx +74 -0
- package/src/features/blog/components/public/BlogSearchBox.tsx +52 -0
- package/src/features/blog/components/public/__tests__/BlogList.spec.tsx +173 -0
- package/src/features/blog/components/public/__tests__/BlogPostView.spec.tsx +128 -0
- package/src/features/blog/components/public/blogPublicHelpers.ts +30 -0
- package/src/features/blog/components/public/index.ts +3 -0
- package/src/features/blog/contexts/BlogPostContext.tsx +66 -0
- package/src/features/blog/contexts/index.ts +1 -0
- package/src/features/blog/data/BlogCategory.ts +93 -0
- package/src/features/blog/data/BlogCategoryFields.ts +4 -0
- package/src/features/blog/data/BlogCategoryInterface.ts +24 -0
- package/src/features/blog/data/BlogCategoryService.ts +54 -0
- package/src/features/blog/data/BlogCategoryTranslation.ts +90 -0
- package/src/features/blog/data/BlogCategoryTranslationInterface.ts +22 -0
- package/src/features/blog/data/BlogCategoryTranslationService.ts +30 -0
- package/src/features/blog/data/BlogPost.spec.ts +123 -0
- package/src/features/blog/data/BlogPost.ts +159 -0
- package/src/features/blog/data/BlogPostFields.ts +7 -0
- package/src/features/blog/data/BlogPostInterface.ts +39 -0
- package/src/features/blog/data/BlogPostService.ts +82 -0
- package/src/features/blog/data/BlogPostTranslation.spec.ts +73 -0
- package/src/features/blog/data/BlogPostTranslation.ts +110 -0
- package/src/features/blog/data/BlogPostTranslationInterface.ts +27 -0
- package/src/features/blog/data/BlogPostTranslationService.ts +30 -0
- package/src/features/blog/data/BlogSettings.ts +37 -0
- package/src/features/blog/data/BlogSettingsInterface.ts +11 -0
- package/src/features/blog/data/BlogSettingsService.ts +24 -0
- package/src/features/blog/data/index.ts +17 -0
- package/src/features/blog/hooks/index.ts +3 -0
- package/src/features/blog/hooks/useBlogCategoryNames.ts +34 -0
- package/src/features/blog/hooks/useBlogCategoryTableStructure.tsx +84 -0
- package/src/features/blog/hooks/useBlogPostTableStructure.tsx +126 -0
- package/src/features/blog/index.ts +15 -0
- package/src/features/blog/server/fetchers.ts +120 -0
- package/src/features/blog/server/toPublic.spec.ts +91 -0
- package/src/features/blog/server/toPublic.ts +36 -0
- package/src/features/blog/server-entry.ts +17 -0
- package/src/features/blog/types/blog-public.types.ts +34 -0
- package/src/features/blog/types/blog.constants.ts +40 -0
- package/src/features/s3/data/s3.service.ts +17 -0
- package/dist/BlockNoteEditor-UJ6363LC.js.map +0 -1
- package/dist/BlockNoteEditor-WTSQANKI.mjs.map +0 -1
- package/dist/chunk-3BAM23VA.js.map +0 -1
- package/dist/chunk-CRI4T47Y.js.map +0 -1
- package/dist/chunk-JQWI62NV.mjs.map +0 -1
- package/dist/chunk-MIZTWBPX.mjs.map +0 -1
- package/dist/chunk-QKZUE5OF.mjs.map +0 -1
- package/dist/chunk-XGTQWBDJ.js.map +0 -1
- /package/dist/{BlockNoteViewer-JVKWJZ6J.mjs.map → BlockNoteViewer-AEJKJ27Q.mjs.map} +0 -0
- /package/dist/{chunk-FNTQQFLH.mjs.map → chunk-6DC2WVVB.mjs.map} +0 -0
- /package/dist/{chunk-6WU74VFU.mjs.map → chunk-QMYQRPQC.mjs.map} +0 -0
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
percentageDelta,
|
|
4
4
|
seriesColor,
|
|
5
5
|
useUsageFormatters
|
|
6
|
-
} from "../../chunk-
|
|
6
|
+
} from "../../chunk-6DC2WVVB.mjs";
|
|
7
7
|
import {
|
|
8
8
|
Badge,
|
|
9
9
|
Button,
|
|
@@ -33,8 +33,8 @@ import {
|
|
|
33
33
|
TabsList,
|
|
34
34
|
TabsTrigger,
|
|
35
35
|
usePageUrlGenerator
|
|
36
|
-
} from "../../chunk-
|
|
37
|
-
import "../../chunk-
|
|
36
|
+
} from "../../chunk-EUKTBOI2.mjs";
|
|
37
|
+
import "../../chunk-QMYQRPQC.mjs";
|
|
38
38
|
import "../../chunk-PW42LRSL.mjs";
|
|
39
39
|
import {
|
|
40
40
|
AbstractService,
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
Modules,
|
|
49
49
|
analyticsModules,
|
|
50
50
|
cn
|
|
51
|
-
} from "../../chunk-
|
|
51
|
+
} from "../../chunk-WC63PJSC.mjs";
|
|
52
52
|
import "../../chunk-AUXK7QSA.mjs";
|
|
53
53
|
import "../../chunk-PI56A4DG.mjs";
|
|
54
54
|
import "../../chunk-V5MI7RNB.mjs";
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkYW4ZCEWBjs = require('../../chunk-YW4ZCEWB.js');
|
|
4
|
+
require('../../chunk-IK65TDQH.js');
|
|
5
|
+
require('../../chunk-KSYQEKJX.js');
|
|
4
6
|
require('../../chunk-YUO55Q5A.js');
|
|
5
7
|
require('../../chunk-6TUB7Y6T.js');
|
|
6
|
-
require('../../chunk-IK65TDQH.js');
|
|
7
8
|
require('../../chunk-G4JR3SFV.js');
|
|
8
|
-
require('../../chunk-
|
|
9
|
+
require('../../chunk-NFBOSPNJ.js');
|
|
9
10
|
require('../../chunk-LXKSUWAV.js');
|
|
10
11
|
require('../../chunk-JTPRJNT2.js');
|
|
11
12
|
require('../../chunk-GHE4VT2R.js');
|
|
@@ -18,7 +19,7 @@ var _navigation = require('next/navigation');
|
|
|
18
19
|
var _analytics = require('@carlonicora/nextjs-jsonapi/analytics');
|
|
19
20
|
var _jsxruntime = require('react/jsx-runtime');
|
|
20
21
|
async function AnalyticsAdminPage({ adminRoleId, pageUrl, sessionPageUrl, deniedRedirect = "/" }) {
|
|
21
|
-
if (!await
|
|
22
|
+
if (!await _chunkYW4ZCEWBjs.ServerSession.hasRole(adminRoleId)) {
|
|
22
23
|
_navigation.redirect.call(void 0, deniedRedirect);
|
|
23
24
|
}
|
|
24
25
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _analytics.AnalyticsAdminPageContainer, { pageUrl, sessionPageUrl });
|
|
@@ -30,7 +31,7 @@ _chunk7QVYU63Ejs.__name.call(void 0, AnalyticsAdminPage, "AnalyticsAdminPage");
|
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
async function AnalyticsJourneyPage({ adminRoleId, sessionId, pageUrl, deniedRedirect = "/" }) {
|
|
33
|
-
if (!await
|
|
34
|
+
if (!await _chunkYW4ZCEWBjs.ServerSession.hasRole(adminRoleId)) {
|
|
34
35
|
_navigation.redirect.call(void 0, deniedRedirect);
|
|
35
36
|
}
|
|
36
37
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _analytics.AnalyticsJourneyPageContainer, { sessionId, pageUrl });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/features/analytics/server.js","../../../src/features/analytics/components/server/AnalyticsAdminPage.tsx","../../../src/features/analytics/components/server/AnalyticsJourneyPage.tsx"],"names":["redirect","jsx"],"mappings":"AAAA;AACE;AACF,0DAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC;AACE;AACF,0DAAgC;AAChC;AACA;
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/features/analytics/server.js","../../../src/features/analytics/components/server/AnalyticsAdminPage.tsx","../../../src/features/analytics/components/server/AnalyticsJourneyPage.tsx"],"names":["redirect","jsx"],"mappings":"AAAA;AACE;AACF,0DAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC,mCAAgC;AAChC;AACE;AACF,0DAAgC;AAChC;AACA;AChBA,6CAAyB;AAMzB,kEAA4C;AAwBnC,+CAAA;AALT,MAAA,SAAsB,kBAAA,CAAmB,EAAE,WAAA,EAAa,OAAA,EAAS,cAAA,EAAgB,eAAA,EAAiB,IAAI,CAAA,EAAU;AAC9G,EAAA,GAAA,CAAI,CAAE,MAAM,8BAAA,CAAc,OAAA,CAAQ,WAAW,CAAA,EAAI;AAC/C,IAAA,kCAAA,cAAuB,CAAA;AAAA,EACzB;AAEA,EAAA,uBAAO,6BAAA,sCAAC,EAAA,EAA4B,OAAA,EAAkB,eAAA,CAAgC,CAAA;AACxF;AANsB,qCAAA,kBAAA,EAAA,oBAAA,CAAA;ADEtB;AACA;AE5BA;AAIA;AAuBS;AALT,MAAA,SAAsB,oBAAA,CAAqB,EAAE,WAAA,EAAa,SAAA,EAAW,OAAA,EAAS,eAAA,EAAiB,IAAI,CAAA,EAAU;AAC3G,EAAA,GAAA,CAAI,CAAE,MAAM,8BAAA,CAAc,OAAA,CAAQ,WAAW,CAAA,EAAI;AAC/C,IAAAA,kCAAAA,cAAuB,CAAA;AAAA,EACzB;AAEA,EAAA,uBAAOC,6BAAAA,wCAAC,EAAA,EAA8B,SAAA,EAAsB,QAAA,CAAkB,CAAA;AAChF;AANsB,qCAAA,oBAAA,EAAA,sBAAA,CAAA;AFiBtB;AACE;AACA;AACF,qGAAC","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/features/analytics/server.js","sourcesContent":[null,"import { redirect } from \"next/navigation\";\n// The container is imported through the package's own client subpath, never by\n// relative path. tsup keeps this specifier external, so the built server entry\n// reaches the container through `features/analytics/index`, which carries the\n// \"use client\" banner. A relative import would inline the container's hooks and\n// contexts into this server bundle, outside any client boundary.\nimport { AnalyticsAdminPageContainer } from \"@carlonicora/nextjs-jsonapi/analytics\";\nimport { ServerSession } from \"../../../../server\";\n\ntype Props = {\n /** Role id the viewer must hold. The package has no role constants, so the host app passes its own. */\n adminRoleId: string;\n /** Route the breadcrumb links back to. */\n pageUrl?: string;\n /** Base route of the journey page each session row links to. */\n sessionPageUrl?: string;\n /** Where a viewer without the role is sent. */\n deniedRedirect?: string;\n};\n\n/**\n * Server page for the administrative analytics dashboard: role gate, then the client container.\n *\n * Reads the session: render inside a `<Suspense>` boundary (Cache Components).\n */\nexport async function AnalyticsAdminPage({ adminRoleId, pageUrl, sessionPageUrl, deniedRedirect = \"/\" }: Props) {\n if (!(await ServerSession.hasRole(adminRoleId))) {\n redirect(deniedRedirect);\n }\n\n return <AnalyticsAdminPageContainer pageUrl={pageUrl} sessionPageUrl={sessionPageUrl} />;\n}\n","import { redirect } from \"next/navigation\";\n// Imported through the package's own client subpath for the same reason as in\n// AnalyticsAdminPage: the built server entry must reach the container through\n// the \"use client\" bundle, not inline it.\nimport { AnalyticsJourneyPageContainer } from \"@carlonicora/nextjs-jsonapi/analytics\";\nimport { ServerSession } from \"../../../../server\";\n\ntype Props = {\n /** Role id the viewer must hold. The package has no role constants, so the host app passes its own. */\n adminRoleId: string;\n sessionId: string;\n /** Route of the dashboard; the journey pages live under `${pageUrl}/sessions`. */\n pageUrl?: string;\n /** Where a viewer without the role is sent. */\n deniedRedirect?: string;\n};\n\n/**\n * Server page for one session's journey: role gate, then the client container.\n *\n * Reads the session: render inside a `<Suspense>` boundary (Cache Components).\n */\nexport async function AnalyticsJourneyPage({ adminRoleId, sessionId, pageUrl, deniedRedirect = \"/\" }: Props) {\n if (!(await ServerSession.hasRole(adminRoleId))) {\n redirect(deniedRedirect);\n }\n\n return <AnalyticsJourneyPageContainer sessionId={sessionId} pageUrl={pageUrl} />;\n}\n"]}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ServerSession
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-XCHSX3VC.mjs";
|
|
4
|
+
import "../../chunk-T7SAW3UW.mjs";
|
|
5
|
+
import "../../chunk-3YW35YHQ.mjs";
|
|
4
6
|
import "../../chunk-F5UNXZ3J.mjs";
|
|
5
7
|
import "../../chunk-E2LENTUH.mjs";
|
|
6
|
-
import "../../chunk-T7SAW3UW.mjs";
|
|
7
8
|
import "../../chunk-PW42LRSL.mjs";
|
|
8
|
-
import "../../chunk-
|
|
9
|
+
import "../../chunk-WC63PJSC.mjs";
|
|
9
10
|
import "../../chunk-AUXK7QSA.mjs";
|
|
10
11
|
import "../../chunk-PI56A4DG.mjs";
|
|
11
12
|
import "../../chunk-V5MI7RNB.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/features/analytics/components/server/AnalyticsAdminPage.tsx","../../../src/features/analytics/components/server/AnalyticsJourneyPage.tsx"],"sourcesContent":["import { redirect } from \"next/navigation\";\n// The container is imported through the package's own client subpath, never by\n// relative path. tsup keeps this specifier external, so the built server entry\n// reaches the container through `features/analytics/index`, which carries the\n// \"use client\" banner. A relative import would inline the container's hooks and\n// contexts into this server bundle, outside any client boundary.\nimport { AnalyticsAdminPageContainer } from \"@carlonicora/nextjs-jsonapi/analytics\";\nimport { ServerSession } from \"../../../../server\";\n\ntype Props = {\n /** Role id the viewer must hold. The package has no role constants, so the host app passes its own. */\n adminRoleId: string;\n /** Route the breadcrumb links back to. */\n pageUrl?: string;\n /** Base route of the journey page each session row links to. */\n sessionPageUrl?: string;\n /** Where a viewer without the role is sent. */\n deniedRedirect?: string;\n};\n\n/**\n * Server page for the administrative analytics dashboard: role gate, then the client container.\n *\n * Reads the session: render inside a `<Suspense>` boundary (Cache Components).\n */\nexport async function AnalyticsAdminPage({ adminRoleId, pageUrl, sessionPageUrl, deniedRedirect = \"/\" }: Props) {\n if (!(await ServerSession.hasRole(adminRoleId))) {\n redirect(deniedRedirect);\n }\n\n return <AnalyticsAdminPageContainer pageUrl={pageUrl} sessionPageUrl={sessionPageUrl} />;\n}\n","import { redirect } from \"next/navigation\";\n// Imported through the package's own client subpath for the same reason as in\n// AnalyticsAdminPage: the built server entry must reach the container through\n// the \"use client\" bundle, not inline it.\nimport { AnalyticsJourneyPageContainer } from \"@carlonicora/nextjs-jsonapi/analytics\";\nimport { ServerSession } from \"../../../../server\";\n\ntype Props = {\n /** Role id the viewer must hold. The package has no role constants, so the host app passes its own. */\n adminRoleId: string;\n sessionId: string;\n /** Route of the dashboard; the journey pages live under `${pageUrl}/sessions`. */\n pageUrl?: string;\n /** Where a viewer without the role is sent. */\n deniedRedirect?: string;\n};\n\n/**\n * Server page for one session's journey: role gate, then the client container.\n *\n * Reads the session: render inside a `<Suspense>` boundary (Cache Components).\n */\nexport async function AnalyticsJourneyPage({ adminRoleId, sessionId, pageUrl, deniedRedirect = \"/\" }: Props) {\n if (!(await ServerSession.hasRole(adminRoleId))) {\n redirect(deniedRedirect);\n }\n\n return <AnalyticsJourneyPageContainer sessionId={sessionId} pageUrl={pageUrl} />;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/features/analytics/components/server/AnalyticsAdminPage.tsx","../../../src/features/analytics/components/server/AnalyticsJourneyPage.tsx"],"sourcesContent":["import { redirect } from \"next/navigation\";\n// The container is imported through the package's own client subpath, never by\n// relative path. tsup keeps this specifier external, so the built server entry\n// reaches the container through `features/analytics/index`, which carries the\n// \"use client\" banner. A relative import would inline the container's hooks and\n// contexts into this server bundle, outside any client boundary.\nimport { AnalyticsAdminPageContainer } from \"@carlonicora/nextjs-jsonapi/analytics\";\nimport { ServerSession } from \"../../../../server\";\n\ntype Props = {\n /** Role id the viewer must hold. The package has no role constants, so the host app passes its own. */\n adminRoleId: string;\n /** Route the breadcrumb links back to. */\n pageUrl?: string;\n /** Base route of the journey page each session row links to. */\n sessionPageUrl?: string;\n /** Where a viewer without the role is sent. */\n deniedRedirect?: string;\n};\n\n/**\n * Server page for the administrative analytics dashboard: role gate, then the client container.\n *\n * Reads the session: render inside a `<Suspense>` boundary (Cache Components).\n */\nexport async function AnalyticsAdminPage({ adminRoleId, pageUrl, sessionPageUrl, deniedRedirect = \"/\" }: Props) {\n if (!(await ServerSession.hasRole(adminRoleId))) {\n redirect(deniedRedirect);\n }\n\n return <AnalyticsAdminPageContainer pageUrl={pageUrl} sessionPageUrl={sessionPageUrl} />;\n}\n","import { redirect } from \"next/navigation\";\n// Imported through the package's own client subpath for the same reason as in\n// AnalyticsAdminPage: the built server entry must reach the container through\n// the \"use client\" bundle, not inline it.\nimport { AnalyticsJourneyPageContainer } from \"@carlonicora/nextjs-jsonapi/analytics\";\nimport { ServerSession } from \"../../../../server\";\n\ntype Props = {\n /** Role id the viewer must hold. The package has no role constants, so the host app passes its own. */\n adminRoleId: string;\n sessionId: string;\n /** Route of the dashboard; the journey pages live under `${pageUrl}/sessions`. */\n pageUrl?: string;\n /** Where a viewer without the role is sent. */\n deniedRedirect?: string;\n};\n\n/**\n * Server page for one session's journey: role gate, then the client container.\n *\n * Reads the session: render inside a `<Suspense>` boundary (Cache Components).\n */\nexport async function AnalyticsJourneyPage({ adminRoleId, sessionId, pageUrl, deniedRedirect = \"/\" }: Props) {\n if (!(await ServerSession.hasRole(adminRoleId))) {\n redirect(deniedRedirect);\n }\n\n return <AnalyticsJourneyPageContainer sessionId={sessionId} pageUrl={pageUrl} />;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA,SAAS,gBAAgB;AAMzB,SAAS,mCAAmC;AAwBnC;AALT,eAAsB,mBAAmB,EAAE,aAAa,SAAS,gBAAgB,iBAAiB,IAAI,GAAU;AAC9G,MAAI,CAAE,MAAM,cAAc,QAAQ,WAAW,GAAI;AAC/C,aAAS,cAAc;AAAA,EACzB;AAEA,SAAO,oBAAC,+BAA4B,SAAkB,gBAAgC;AACxF;AANsB;;;ACzBtB,SAAS,YAAAA,iBAAgB;AAIzB,SAAS,qCAAqC;AAuBrC,gBAAAC,YAAA;AALT,eAAsB,qBAAqB,EAAE,aAAa,WAAW,SAAS,iBAAiB,IAAI,GAAU;AAC3G,MAAI,CAAE,MAAM,cAAc,QAAQ,WAAW,GAAI;AAC/C,IAAAC,UAAS,cAAc;AAAA,EACzB;AAEA,SAAO,gBAAAD,KAAC,iCAA8B,WAAsB,SAAkB;AAChF;AANsB;","names":["redirect","jsx","redirect"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* src/features/onboarding/styles/onboarding.css */
|
|
2
|
+
.driver-popover.onboarding-popover {
|
|
3
|
+
background: transparent;
|
|
4
|
+
box-shadow: none;
|
|
5
|
+
padding: 0;
|
|
6
|
+
border-radius: 0;
|
|
7
|
+
max-width: none;
|
|
8
|
+
width: auto;
|
|
9
|
+
overflow: visible;
|
|
10
|
+
color: inherit;
|
|
11
|
+
}
|
|
12
|
+
.driver-popover.onboarding-popover .driver-popover-title,
|
|
13
|
+
.driver-popover.onboarding-popover .driver-popover-description,
|
|
14
|
+
.driver-popover.onboarding-popover .driver-popover-footer,
|
|
15
|
+
.driver-popover.onboarding-popover .driver-popover-close-btn {
|
|
16
|
+
display: none;
|
|
17
|
+
}
|
|
18
|
+
.driver-popover.onboarding-popover .driver-popover-arrow-side-top {
|
|
19
|
+
border-top-color: var(--card);
|
|
20
|
+
}
|
|
21
|
+
.driver-popover.onboarding-popover .driver-popover-arrow-side-bottom {
|
|
22
|
+
border-bottom-color: var(--card);
|
|
23
|
+
}
|
|
24
|
+
.driver-popover.onboarding-popover .driver-popover-arrow-side-left {
|
|
25
|
+
border-left-color: var(--card);
|
|
26
|
+
}
|
|
27
|
+
.driver-popover.onboarding-popover .driver-popover-arrow-side-right {
|
|
28
|
+
border-right-color: var(--card);
|
|
29
|
+
}
|
|
30
|
+
/*# sourceMappingURL=index.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/features/onboarding/styles/onboarding.css"],"sourcesContent":["/* driver.js chrome is hidden: the React card mounted by OnboardingContext is the whole popover. */\n.driver-popover.onboarding-popover {\n background: transparent;\n box-shadow: none;\n padding: 0;\n border-radius: 0;\n max-width: none;\n width: auto;\n /* The card is the popover; driver.js's own clipping would cut it off. */\n overflow: visible;\n color: inherit;\n}\n\n.driver-popover.onboarding-popover .driver-popover-title,\n.driver-popover.onboarding-popover .driver-popover-description,\n.driver-popover.onboarding-popover .driver-popover-footer,\n.driver-popover.onboarding-popover .driver-popover-close-btn {\n display: none;\n}\n\n/* Arrow colour follows the card surface so it reads as part of it. */\n.driver-popover.onboarding-popover .driver-popover-arrow-side-top {\n border-top-color: var(--card);\n}\n.driver-popover.onboarding-popover .driver-popover-arrow-side-bottom {\n border-bottom-color: var(--card);\n}\n.driver-popover.onboarding-popover .driver-popover-arrow-side-left {\n border-left-color: var(--card);\n}\n.driver-popover.onboarding-popover .driver-popover-arrow-side-right {\n border-right-color: var(--card);\n}\n"],"mappings":";AACA,CAAC,cAAc,CAAC;AACd,cAAY;AACZ,cAAY;AACZ,WAAS;AACT,iBAAe;AACf,aAAW;AACX,SAAO;AAEP,YAAU;AACV,SAAO;AACT;AAEA,CAZC,cAYc,CAZC,mBAYmB,CAAC;AACpC,CAbC,cAac,CAbC,mBAamB,CAAC;AACpC,CAdC,cAcc,CAdC,mBAcmB,CAAC;AACpC,CAfC,cAec,CAfC,mBAemB,CAAC;AAClC,WAAS;AACX;AAGA,CApBC,cAoBc,CApBC,mBAoBmB,CAAC;AAClC,oBAAkB,IAAI;AACxB;AACA,CAvBC,cAuBc,CAvBC,mBAuBmB,CAAC;AAClC,uBAAqB,IAAI;AAC3B;AACA,CA1BC,cA0Bc,CA1BC,mBA0BmB,CAAC;AAClC,qBAAmB,IAAI;AACzB;AACA,CA7BC,cA6Bc,CA7BC,mBA6BmB,CAAC;AAClC,sBAAoB,IAAI;AAC1B;","names":[]}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { b as BlogPostInterface, a as BlogCategoryInterface, f as BlogPostTranslationInterface, j as BlogAiStatus, B as BlogListLayout } from '../../BlogPostInterface-BB_4wcDR.mjs';
|
|
4
|
+
export { u as BLOG_ACTION, s as BLOG_CATEGORY_UPLOAD_PREFIX, c as BLOG_LIST_LAYOUTS, p as BLOG_MODULE_ID, k as BLOG_POST_STATUSES, r as BLOG_POST_UPLOAD_PREFIX, t as BLOG_PUBLIC_PREFIX, o as BLOG_SETTINGS_ID, m as BLOG_TRANSLATION_SOURCES, q as BLOG_UPLOAD_ROOT, l as BlogPostStatus, n as BlogTranslationSource } from '../../BlogPostInterface-BB_4wcDR.mjs';
|
|
5
|
+
import { b as PublicBlogList, P as PublicBlogCategory, a as PublicBlogPost } from '../../blog-public.types-BbrzsC1c.mjs';
|
|
6
|
+
import { U as UseTableStructureHook } from '../../types-70acd-8C.mjs';
|
|
7
|
+
import { B as BlogPostFields, a as BlogCategoryFields } from '../../BlogCategoryFields-DO48vOTE.mjs';
|
|
8
|
+
import '../../ApiDataInterface-BcZeXy5X.mjs';
|
|
9
|
+
import '../../user.interface-CIWGlbqM.mjs';
|
|
10
|
+
import '../../feature.interface-CXb1-vNq.mjs';
|
|
11
|
+
import '@blocknote/core';
|
|
12
|
+
import '@tanstack/react-table';
|
|
13
|
+
import '../../types-Bq_UA8Lg.mjs';
|
|
14
|
+
import 'lucide-react';
|
|
15
|
+
import '../../ApiRequestDataTypeInterface-CYEcRUrh.mjs';
|
|
16
|
+
import '../../useDataListRetriever-WEXL4bqB.mjs';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Blog admin page: posts, categories and the public list layout, one tab each.
|
|
20
|
+
* Client component because `module={Modules.BlogPost}` carries an icon component.
|
|
21
|
+
* Mirrors features/email-automation/components/containers/EmailAutomationsListContainer.tsx.
|
|
22
|
+
*/
|
|
23
|
+
declare function BlogAdminContainer(): React.JSX.Element;
|
|
24
|
+
|
|
25
|
+
type BlogPostContainerProps = {
|
|
26
|
+
postId: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Admin post page: one tab per language, the original first and marked
|
|
30
|
+
* "Original" (approved mockup A). Mirrors
|
|
31
|
+
* features/email-automation/components/containers/EmailAutomationContainer.tsx.
|
|
32
|
+
*/
|
|
33
|
+
declare function BlogPostContainer({ postId }: BlogPostContainerProps): React.JSX.Element;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Admin posts table: title (original language, links to the post page),
|
|
37
|
+
* status, categories, published date and "languages ready" (completed
|
|
38
|
+
* translations / all translations). Mirrors hooks/useEmailAutomationTableStructure.tsx
|
|
39
|
+
* in features/email-automation.
|
|
40
|
+
*/
|
|
41
|
+
declare const useBlogPostTableStructure: UseTableStructureHook<BlogPostInterface, BlogPostFields>;
|
|
42
|
+
|
|
43
|
+
type BlogPostsListProps = {
|
|
44
|
+
/** Pass when the list is the page's own content inside a `RoundPageContainer fullWidth`. */
|
|
45
|
+
fullWidth?: boolean;
|
|
46
|
+
};
|
|
47
|
+
/** Admin posts table. Mirrors features/email-automation/components/lists/EmailAutomationsList.tsx. */
|
|
48
|
+
declare function BlogPostsList({ fullWidth }?: BlogPostsListProps): React.JSX.Element;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Admin categories table: the name (original language) opens BlogCategoryEditor
|
|
52
|
+
* for that row; "languages ready" counts completed translations. Categories have
|
|
53
|
+
* no page of their own. Mirrors hooks/useEmailAutomationTableStructure.tsx in
|
|
54
|
+
* features/email-automation.
|
|
55
|
+
*/
|
|
56
|
+
declare const useBlogCategoryTableStructure: UseTableStructureHook<BlogCategoryInterface, BlogCategoryFields>;
|
|
57
|
+
|
|
58
|
+
type BlogCategoriesListProps = {
|
|
59
|
+
/** Pass when the list is the page's own content inside a `RoundPageContainer fullWidth`. */
|
|
60
|
+
fullWidth?: boolean;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Admin categories table. Categories have no page of their own: creating and
|
|
64
|
+
* editing both stay on this tab and refresh the list.
|
|
65
|
+
* Mirrors features/email-automation/components/lists/EmailAutomationsList.tsx.
|
|
66
|
+
*/
|
|
67
|
+
declare function BlogCategoriesList({ fullWidth }?: BlogCategoriesListProps): React.JSX.Element;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Picks the public list layout (featured / column / rail). The choice is saved
|
|
71
|
+
* at once and the public blog uses it within the cache window.
|
|
72
|
+
*/
|
|
73
|
+
declare function BlogLayoutSetting(): React.JSX.Element;
|
|
74
|
+
|
|
75
|
+
type BlogPostTranslationPanelProps = {
|
|
76
|
+
post: BlogPostInterface;
|
|
77
|
+
translation: BlogPostTranslationInterface;
|
|
78
|
+
/** Re-reads the post after an edit or a re-translation request. */
|
|
79
|
+
onChanged?: () => Promise<void>;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* One language tab of the admin post page (approved mockup A).
|
|
83
|
+
* - Original tab: cover image, categories, status, the text fields and an Edit
|
|
84
|
+
* that opens BlogPostEditor (which re-translates every other language).
|
|
85
|
+
* - Translation tab: where the text came from, whether it was edited by hand,
|
|
86
|
+
* the overwrite warning, "Compare with original", the job status, the text
|
|
87
|
+
* fields and an Edit that opens BlogPostTranslationEditor.
|
|
88
|
+
*/
|
|
89
|
+
declare function BlogPostTranslationPanel({ post, translation, onChanged }: BlogPostTranslationPanelProps): React.JSX.Element;
|
|
90
|
+
|
|
91
|
+
type BlogPostComparisonProps = {
|
|
92
|
+
original: BlogPostTranslationInterface;
|
|
93
|
+
translation: BlogPostTranslationInterface;
|
|
94
|
+
};
|
|
95
|
+
/** One language's text fields, read-only. Shared by both sides of the comparison. */
|
|
96
|
+
declare function BlogPostTranslationFields({ translation }: {
|
|
97
|
+
translation: BlogPostTranslationInterface;
|
|
98
|
+
}): React.JSX.Element;
|
|
99
|
+
/** Original on the inline start, translation on the inline end, same fields (mockup A → B's split view). */
|
|
100
|
+
declare function BlogPostComparison({ original, translation }: BlogPostComparisonProps): React.JSX.Element;
|
|
101
|
+
|
|
102
|
+
/** Status pill colours for a post, shared by the post header and the admin posts table. */
|
|
103
|
+
declare const BLOG_STATUS_BADGE: {
|
|
104
|
+
readonly draft: "softGray";
|
|
105
|
+
readonly published: "softGreen";
|
|
106
|
+
readonly unpublished: "softAmber";
|
|
107
|
+
};
|
|
108
|
+
/** The category label in the admin: the category's own original-language name. */
|
|
109
|
+
declare function blogCategoryAdminName(category: BlogCategoryInterface): string;
|
|
110
|
+
/**
|
|
111
|
+
* Language names come from `Intl.DisplayNames` in the viewer's locale: there is
|
|
112
|
+
* no per-language message key. An unknown code falls back to the code itself.
|
|
113
|
+
*/
|
|
114
|
+
declare function useBlogLanguageName(): (language: string) => string;
|
|
115
|
+
/** Formats a date for the admin pages in the viewer's locale. */
|
|
116
|
+
declare function useBlogDateFormatter(): (date?: Date) => string;
|
|
117
|
+
type BlogTranslationStatusProps = {
|
|
118
|
+
aiStatus: BlogAiStatus;
|
|
119
|
+
/** Re-queues the translation of this one language. Shown only when the job failed. */
|
|
120
|
+
onRetranslate?: () => Promise<void>;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* The translation state of one language. Nothing is rendered once the
|
|
124
|
+
* translation is `completed`; `failed` adds the "Translate again" action.
|
|
125
|
+
*/
|
|
126
|
+
declare function BlogTranslationStatus({ aiStatus, onRetranslate }: BlogTranslationStatusProps): React.JSX.Element | null;
|
|
127
|
+
|
|
128
|
+
type BlogPostEditorProps = {
|
|
129
|
+
/** Edit mode when present: the post's original translation and shared fields. */
|
|
130
|
+
post?: BlogPostInterface;
|
|
131
|
+
trigger?: ReactNode;
|
|
132
|
+
onSuccess?: () => void | Promise<void>;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Creates a post, or edits its original-language text plus the fields every
|
|
136
|
+
* language shares (cover image, categories). Saving the original makes the
|
|
137
|
+
* worker translate it again. Mirrors features/how-to/components/forms/HowToEditor.tsx.
|
|
138
|
+
*/
|
|
139
|
+
declare function BlogPostEditor({ post, trigger, onSuccess }: BlogPostEditorProps): React.JSX.Element;
|
|
140
|
+
|
|
141
|
+
type BlogPostTranslationEditorProps = {
|
|
142
|
+
translation: BlogPostTranslationInterface;
|
|
143
|
+
trigger?: ReactNode;
|
|
144
|
+
onSuccess?: () => void | Promise<void>;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Edits one non-original translation by hand. Saving marks it `manual` and
|
|
148
|
+
* re-runs nothing. Mirrors features/how-to/components/forms/HowToEditor.tsx.
|
|
149
|
+
*/
|
|
150
|
+
declare function BlogPostTranslationEditor({ translation, trigger, onSuccess }: BlogPostTranslationEditorProps): React.JSX.Element;
|
|
151
|
+
|
|
152
|
+
type BlogCategoryEditorProps = {
|
|
153
|
+
/** Edit mode when present. */
|
|
154
|
+
category?: BlogCategoryInterface;
|
|
155
|
+
trigger?: ReactNode;
|
|
156
|
+
onSuccess?: () => void | Promise<void>;
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Creates a category, or edits its original-language text and image plus, in
|
|
160
|
+
* edit mode, each AI translation by hand (one collapsible section per language).
|
|
161
|
+
* Submit updates the category when the original changed (which re-translates
|
|
162
|
+
* every other language) and each translation that changed (marked `manual`).
|
|
163
|
+
* Mirrors features/how-to/components/forms/HowToEditor.tsx.
|
|
164
|
+
*/
|
|
165
|
+
declare function BlogCategoryEditor({ category, trigger, onSuccess }: BlogCategoryEditorProps): React.JSX.Element;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Publish / Unpublish in the post page header. Publishing an unpublished post
|
|
169
|
+
* republishes it (the first publish date is kept server-side).
|
|
170
|
+
* Mirrors features/email-automation/components/canvas/EmailAutomationActiveSwitch.tsx.
|
|
171
|
+
*/
|
|
172
|
+
declare function BlogPostPublishButton(): React.JSX.Element | null;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Deletes the post and returns to the blog admin page.
|
|
176
|
+
* Mirrors features/how-to/components/forms/HowToDeleter.tsx. The dialog texts
|
|
177
|
+
* are passed explicitly: CommonDeleter's default reads `entities.<type>`, a
|
|
178
|
+
* namespace only the app may fill, so the blog's own entity name is used.
|
|
179
|
+
*/
|
|
180
|
+
declare function BlogPostDeleter(): React.JSX.Element | null;
|
|
181
|
+
|
|
182
|
+
/** A picked image waiting to be uploaded: the S3 key is already in the form field. */
|
|
183
|
+
type BlogImageSelection = {
|
|
184
|
+
file: File;
|
|
185
|
+
contentType: string;
|
|
186
|
+
} | null;
|
|
187
|
+
/** Uploads a picked image to its presigned S3 key. */
|
|
188
|
+
declare function uploadBlogImage(params: {
|
|
189
|
+
key: string;
|
|
190
|
+
selection: BlogImageSelection;
|
|
191
|
+
}): Promise<void>;
|
|
192
|
+
type BlogCoverImageFieldProps = {
|
|
193
|
+
form: any;
|
|
194
|
+
/** The form field that receives the new S3 key ("coverImage" or "image"). */
|
|
195
|
+
id: string;
|
|
196
|
+
label: string;
|
|
197
|
+
/** BLOG_POST_UPLOAD_PREFIX or BLOG_CATEGORY_UPLOAD_PREFIX. */
|
|
198
|
+
keyPrefix: string;
|
|
199
|
+
/** The id of the post or category the image belongs to. */
|
|
200
|
+
entityId: string;
|
|
201
|
+
/** The signed URL of the image already stored, for the preview. */
|
|
202
|
+
currentUrl?: string;
|
|
203
|
+
alt?: string;
|
|
204
|
+
selection: BlogImageSelection;
|
|
205
|
+
onSelectionChange: (selection: BlogImageSelection) => void;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Dropzone for a post cover or a category image. Picking a file writes its S3
|
|
209
|
+
* key (`<keyPrefix>/<id>/<id>.<timestamp>.<ext>`, under the platform blog root,
|
|
210
|
+
* see BLOG_UPLOAD_ROOT) into the form field and hands
|
|
211
|
+
* the file to the editor, which uploads it with `uploadBlogImage` on submit.
|
|
212
|
+
*/
|
|
213
|
+
declare function BlogCoverImageField({ form, id, label, keyPrefix, entityId, currentUrl, alt, selection, onSelectionChange, }: BlogCoverImageFieldProps): React.JSX.Element;
|
|
214
|
+
|
|
215
|
+
type BlogListProps = {
|
|
216
|
+
layout: BlogListLayout;
|
|
217
|
+
list: PublicBlogList;
|
|
218
|
+
categories: PublicBlogCategory[];
|
|
219
|
+
activeCategorySlug?: string;
|
|
220
|
+
query?: string;
|
|
221
|
+
page: number;
|
|
222
|
+
basePath: string;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/** Public blog list in the layout an administrator picked (BlogSettings.listLayout). */
|
|
226
|
+
declare function BlogList(props: BlogListProps): React.JSX.Element;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Public post page: back link, category, title, summary, meta, cover, body,
|
|
230
|
+
* then up to three posts from the same category.
|
|
231
|
+
*/
|
|
232
|
+
declare function BlogPostView(props: {
|
|
233
|
+
post: PublicBlogPost;
|
|
234
|
+
categories: PublicBlogCategory[];
|
|
235
|
+
related: PublicBlogPost[];
|
|
236
|
+
basePath: string;
|
|
237
|
+
}): React.JSX.Element;
|
|
238
|
+
|
|
239
|
+
interface BlogPostContextType {
|
|
240
|
+
post: BlogPostInterface | undefined;
|
|
241
|
+
reload: () => Promise<void>;
|
|
242
|
+
}
|
|
243
|
+
type BlogPostProviderProps = {
|
|
244
|
+
postId: string;
|
|
245
|
+
children: ReactNode;
|
|
246
|
+
};
|
|
247
|
+
/**
|
|
248
|
+
* Loads one post (with its translations, categories and author) for the admin
|
|
249
|
+
* post page. While any translation is `pending` or `in_progress` it re-reads
|
|
250
|
+
* the post every 5 s, so the language tabs move from "Translating…" to the
|
|
251
|
+
* translated text without a manual refresh; it stops once none are running.
|
|
252
|
+
*/
|
|
253
|
+
declare const BlogPostProvider: ({ postId, children }: BlogPostProviderProps) => React.JSX.Element;
|
|
254
|
+
declare const useBlogPost: () => BlogPostContextType;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Category names for the admin views, in each category's original language.
|
|
258
|
+
*
|
|
259
|
+
* A post response includes its categories without their translations (the
|
|
260
|
+
* framework includes one level), so the name is not on the included record.
|
|
261
|
+
* The category list does include the translations: it is read once and the
|
|
262
|
+
* returned lookup maps a category id to its name ("" while loading).
|
|
263
|
+
*/
|
|
264
|
+
declare function useBlogCategoryNames(): (categoryId: string) => string;
|
|
265
|
+
|
|
266
|
+
export { BLOG_STATUS_BADGE, BlogAdminContainer, BlogAiStatus, BlogCategoriesList, BlogCategoryEditor, BlogCoverImageField, type BlogImageSelection, BlogLayoutSetting, BlogList, BlogListLayout, type BlogListProps, BlogPostComparison, BlogPostContainer, type BlogPostContainerProps, type BlogPostContextType, BlogPostDeleter, BlogPostEditor, BlogPostProvider, type BlogPostProviderProps, BlogPostPublishButton, BlogPostTranslationEditor, BlogPostTranslationFields, BlogPostTranslationPanel, BlogPostView, BlogPostsList, BlogTranslationStatus, PublicBlogCategory, PublicBlogList, PublicBlogPost, blogCategoryAdminName, uploadBlogImage, useBlogCategoryNames, useBlogCategoryTableStructure, useBlogDateFormatter, useBlogLanguageName, useBlogPost, useBlogPostTableStructure };
|