@btst/stack 1.5.0 → 1.5.1
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/packages/better-stack/src/plugins/blog/client/components/pages/edit-post-page.internal.cjs +7 -6
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/edit-post-page.internal.mjs +7 -6
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/home-page.internal.cjs +9 -7
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/home-page.internal.mjs +9 -7
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/new-post-page.internal.cjs +7 -6
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/new-post-page.internal.mjs +7 -6
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +7 -5
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +7 -5
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/tag-page.internal.cjs +5 -3
- package/dist/packages/better-stack/src/plugins/blog/client/components/pages/tag-page.internal.mjs +5 -3
- package/dist/packages/better-stack/src/plugins/blog/client/plugin.cjs +6 -6
- package/dist/packages/better-stack/src/plugins/blog/client/plugin.mjs +6 -6
- package/dist/packages/better-stack/src/plugins/cms/client/components/pages/content-editor-page.internal.cjs +19 -2
- package/dist/packages/better-stack/src/plugins/cms/client/components/pages/content-editor-page.internal.mjs +19 -2
- package/dist/packages/better-stack/src/plugins/cms/client/components/pages/content-list-page.internal.cjs +19 -6
- package/dist/packages/better-stack/src/plugins/cms/client/components/pages/content-list-page.internal.mjs +19 -6
- package/dist/packages/better-stack/src/plugins/cms/client/components/pages/dashboard-page.internal.cjs +18 -2
- package/dist/packages/better-stack/src/plugins/cms/client/components/pages/dashboard-page.internal.mjs +18 -2
- package/dist/packages/better-stack/src/plugins/cms/client/plugin.cjs +112 -22
- package/dist/packages/better-stack/src/plugins/cms/client/plugin.mjs +112 -22
- package/dist/packages/{better-stack/src/plugins/blog/client/components/shared → ui/src/hooks}/use-route-lifecycle.cjs +8 -9
- package/dist/packages/{better-stack/src/plugins/blog/client/components/shared → ui/src/hooks}/use-route-lifecycle.mjs +1 -2
- package/dist/plugins/blog/api/index.d.cts +1 -1
- package/dist/plugins/blog/api/index.d.mts +1 -1
- package/dist/plugins/blog/api/index.d.ts +1 -1
- package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
- package/dist/plugins/blog/client/index.d.cts +1 -1
- package/dist/plugins/blog/client/index.d.mts +1 -1
- package/dist/plugins/blog/client/index.d.ts +1 -1
- package/dist/plugins/blog/query-keys.d.cts +2 -2
- package/dist/plugins/blog/query-keys.d.mts +2 -2
- package/dist/plugins/blog/query-keys.d.ts +2 -2
- package/dist/plugins/cms/client/index.d.cts +66 -1
- package/dist/plugins/cms/client/index.d.mts +66 -1
- package/dist/plugins/cms/client/index.d.ts +66 -1
- package/package.json +1 -1
- package/src/plugins/blog/client/components/pages/edit-post-page.internal.tsx +4 -3
- package/src/plugins/blog/client/components/pages/home-page.internal.tsx +4 -2
- package/src/plugins/blog/client/components/pages/new-post-page.internal.tsx +4 -3
- package/src/plugins/blog/client/components/pages/post-page.internal.tsx +4 -2
- package/src/plugins/blog/client/components/pages/tag-page.internal.tsx +4 -2
- package/src/plugins/blog/client/plugin.tsx +10 -9
- package/src/plugins/cms/client/components/pages/content-editor-page.internal.tsx +21 -3
- package/src/plugins/cms/client/components/pages/content-list-page.internal.tsx +21 -6
- package/src/plugins/cms/client/components/pages/dashboard-page.internal.tsx +20 -3
- package/src/plugins/cms/client/index.ts +1 -1
- package/src/plugins/cms/client/plugin.tsx +236 -25
- package/src/plugins/blog/client/components/shared/use-route-lifecycle.tsx +0 -68
- package/dist/shared/{stack.CcI4sYJP.d.ts → stack.DLhzx1-D.d.cts} +1 -1
- package/dist/shared/{stack.CcI4sYJP.d.cts → stack.DLhzx1-D.d.mts} +1 -1
- package/dist/shared/{stack.CcI4sYJP.d.mts → stack.DLhzx1-D.d.ts} +1 -1
|
@@ -12,23 +12,88 @@ import 'zod';
|
|
|
12
12
|
* Context passed to loader hooks
|
|
13
13
|
*/
|
|
14
14
|
interface LoaderContext {
|
|
15
|
+
/** Current route path */
|
|
15
16
|
path: string;
|
|
17
|
+
/** Route parameters (e.g., { typeSlug: "product", id: "123" }) */
|
|
16
18
|
params?: Record<string, string>;
|
|
19
|
+
/** Whether rendering on server (true) or client (false) */
|
|
17
20
|
isSSR: boolean;
|
|
21
|
+
/** Base URL for API calls */
|
|
18
22
|
apiBaseURL: string;
|
|
23
|
+
/** Path where the API is mounted */
|
|
19
24
|
apiBasePath: string;
|
|
25
|
+
/** Optional headers for the request */
|
|
20
26
|
headers?: Headers;
|
|
27
|
+
/** Additional context properties */
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Hooks for CMS client plugin
|
|
32
|
+
* All hooks are optional and allow consumers to customize behavior
|
|
33
|
+
*/
|
|
34
|
+
interface CMSClientHooks {
|
|
35
|
+
/**
|
|
36
|
+
* Called before loading the dashboard page. Return false to cancel loading.
|
|
37
|
+
* @param context - Loader context with path, params, etc.
|
|
38
|
+
*/
|
|
39
|
+
beforeLoadDashboard?: (context: LoaderContext) => Promise<boolean> | boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Called after the dashboard is loaded.
|
|
42
|
+
* @param context - Loader context
|
|
43
|
+
*/
|
|
44
|
+
afterLoadDashboard?: (context: LoaderContext) => Promise<void> | void;
|
|
45
|
+
/**
|
|
46
|
+
* Called before loading a content list page. Return false to cancel loading.
|
|
47
|
+
* @param typeSlug - The content type slug
|
|
48
|
+
* @param context - Loader context
|
|
49
|
+
*/
|
|
50
|
+
beforeLoadContentList?: (typeSlug: string, context: LoaderContext) => Promise<boolean> | boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Called after a content list is loaded.
|
|
53
|
+
* @param typeSlug - The content type slug
|
|
54
|
+
* @param context - Loader context
|
|
55
|
+
*/
|
|
56
|
+
afterLoadContentList?: (typeSlug: string, context: LoaderContext) => Promise<void> | void;
|
|
57
|
+
/**
|
|
58
|
+
* Called before loading the content editor page. Return false to cancel loading.
|
|
59
|
+
* @param typeSlug - The content type slug
|
|
60
|
+
* @param id - The content item ID (undefined for new items)
|
|
61
|
+
* @param context - Loader context
|
|
62
|
+
*/
|
|
63
|
+
beforeLoadContentEditor?: (typeSlug: string, id: string | undefined, context: LoaderContext) => Promise<boolean> | boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Called after the content editor is loaded.
|
|
66
|
+
* @param typeSlug - The content type slug
|
|
67
|
+
* @param id - The content item ID (undefined for new items)
|
|
68
|
+
* @param context - Loader context
|
|
69
|
+
*/
|
|
70
|
+
afterLoadContentEditor?: (typeSlug: string, id: string | undefined, context: LoaderContext) => Promise<void> | void;
|
|
71
|
+
/**
|
|
72
|
+
* Called when a loading error occurs.
|
|
73
|
+
* Use this for redirects on authorization failures.
|
|
74
|
+
* @param error - The error that occurred
|
|
75
|
+
* @param context - Loader context
|
|
76
|
+
*/
|
|
77
|
+
onLoadError?: (error: Error, context: LoaderContext) => Promise<void> | void;
|
|
21
78
|
}
|
|
22
79
|
/**
|
|
23
80
|
* Configuration for CMS client plugin
|
|
24
81
|
*/
|
|
25
82
|
interface CMSClientConfig {
|
|
83
|
+
/** Base URL for API calls (e.g., "http://localhost:3000") */
|
|
26
84
|
apiBaseURL: string;
|
|
85
|
+
/** Path where the API is mounted (e.g., "/api/data") */
|
|
27
86
|
apiBasePath: string;
|
|
87
|
+
/** Base URL of your site */
|
|
28
88
|
siteBaseURL: string;
|
|
89
|
+
/** Path where pages are mounted (e.g., "/pages") */
|
|
29
90
|
siteBasePath: string;
|
|
91
|
+
/** React Query client instance for caching */
|
|
30
92
|
queryClient: QueryClient;
|
|
93
|
+
/** Optional headers for SSR (e.g., forwarding cookies) */
|
|
31
94
|
headers?: Headers;
|
|
95
|
+
/** Optional hooks for customizing behavior (authorization, redirects, etc.) */
|
|
96
|
+
hooks?: CMSClientHooks;
|
|
32
97
|
}
|
|
33
98
|
/**
|
|
34
99
|
* CMS client plugin
|
|
@@ -341,4 +406,4 @@ interface CMSFileUploadProps extends AutoFormInputComponentProps {
|
|
|
341
406
|
declare function CMSFileUpload({ label, isRequired, fieldConfigItem, fieldProps, field, uploadImage, }: CMSFileUploadProps): react_jsx_runtime.JSX.Element;
|
|
342
407
|
|
|
343
408
|
export { AutoFormInputComponentProps, CMSFileUpload, cmsClientPlugin };
|
|
344
|
-
export type { CMSClientConfig, CMSFileUploadProps, CMSLocalization, CMSPluginOverrides, LoaderContext, RouteContext };
|
|
409
|
+
export type { CMSClientConfig, CMSClientHooks, CMSFileUploadProps, CMSLocalization, CMSPluginOverrides, LoaderContext, RouteContext };
|
|
@@ -12,23 +12,88 @@ import 'zod';
|
|
|
12
12
|
* Context passed to loader hooks
|
|
13
13
|
*/
|
|
14
14
|
interface LoaderContext {
|
|
15
|
+
/** Current route path */
|
|
15
16
|
path: string;
|
|
17
|
+
/** Route parameters (e.g., { typeSlug: "product", id: "123" }) */
|
|
16
18
|
params?: Record<string, string>;
|
|
19
|
+
/** Whether rendering on server (true) or client (false) */
|
|
17
20
|
isSSR: boolean;
|
|
21
|
+
/** Base URL for API calls */
|
|
18
22
|
apiBaseURL: string;
|
|
23
|
+
/** Path where the API is mounted */
|
|
19
24
|
apiBasePath: string;
|
|
25
|
+
/** Optional headers for the request */
|
|
20
26
|
headers?: Headers;
|
|
27
|
+
/** Additional context properties */
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Hooks for CMS client plugin
|
|
32
|
+
* All hooks are optional and allow consumers to customize behavior
|
|
33
|
+
*/
|
|
34
|
+
interface CMSClientHooks {
|
|
35
|
+
/**
|
|
36
|
+
* Called before loading the dashboard page. Return false to cancel loading.
|
|
37
|
+
* @param context - Loader context with path, params, etc.
|
|
38
|
+
*/
|
|
39
|
+
beforeLoadDashboard?: (context: LoaderContext) => Promise<boolean> | boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Called after the dashboard is loaded.
|
|
42
|
+
* @param context - Loader context
|
|
43
|
+
*/
|
|
44
|
+
afterLoadDashboard?: (context: LoaderContext) => Promise<void> | void;
|
|
45
|
+
/**
|
|
46
|
+
* Called before loading a content list page. Return false to cancel loading.
|
|
47
|
+
* @param typeSlug - The content type slug
|
|
48
|
+
* @param context - Loader context
|
|
49
|
+
*/
|
|
50
|
+
beforeLoadContentList?: (typeSlug: string, context: LoaderContext) => Promise<boolean> | boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Called after a content list is loaded.
|
|
53
|
+
* @param typeSlug - The content type slug
|
|
54
|
+
* @param context - Loader context
|
|
55
|
+
*/
|
|
56
|
+
afterLoadContentList?: (typeSlug: string, context: LoaderContext) => Promise<void> | void;
|
|
57
|
+
/**
|
|
58
|
+
* Called before loading the content editor page. Return false to cancel loading.
|
|
59
|
+
* @param typeSlug - The content type slug
|
|
60
|
+
* @param id - The content item ID (undefined for new items)
|
|
61
|
+
* @param context - Loader context
|
|
62
|
+
*/
|
|
63
|
+
beforeLoadContentEditor?: (typeSlug: string, id: string | undefined, context: LoaderContext) => Promise<boolean> | boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Called after the content editor is loaded.
|
|
66
|
+
* @param typeSlug - The content type slug
|
|
67
|
+
* @param id - The content item ID (undefined for new items)
|
|
68
|
+
* @param context - Loader context
|
|
69
|
+
*/
|
|
70
|
+
afterLoadContentEditor?: (typeSlug: string, id: string | undefined, context: LoaderContext) => Promise<void> | void;
|
|
71
|
+
/**
|
|
72
|
+
* Called when a loading error occurs.
|
|
73
|
+
* Use this for redirects on authorization failures.
|
|
74
|
+
* @param error - The error that occurred
|
|
75
|
+
* @param context - Loader context
|
|
76
|
+
*/
|
|
77
|
+
onLoadError?: (error: Error, context: LoaderContext) => Promise<void> | void;
|
|
21
78
|
}
|
|
22
79
|
/**
|
|
23
80
|
* Configuration for CMS client plugin
|
|
24
81
|
*/
|
|
25
82
|
interface CMSClientConfig {
|
|
83
|
+
/** Base URL for API calls (e.g., "http://localhost:3000") */
|
|
26
84
|
apiBaseURL: string;
|
|
85
|
+
/** Path where the API is mounted (e.g., "/api/data") */
|
|
27
86
|
apiBasePath: string;
|
|
87
|
+
/** Base URL of your site */
|
|
28
88
|
siteBaseURL: string;
|
|
89
|
+
/** Path where pages are mounted (e.g., "/pages") */
|
|
29
90
|
siteBasePath: string;
|
|
91
|
+
/** React Query client instance for caching */
|
|
30
92
|
queryClient: QueryClient;
|
|
93
|
+
/** Optional headers for SSR (e.g., forwarding cookies) */
|
|
31
94
|
headers?: Headers;
|
|
95
|
+
/** Optional hooks for customizing behavior (authorization, redirects, etc.) */
|
|
96
|
+
hooks?: CMSClientHooks;
|
|
32
97
|
}
|
|
33
98
|
/**
|
|
34
99
|
* CMS client plugin
|
|
@@ -341,4 +406,4 @@ interface CMSFileUploadProps extends AutoFormInputComponentProps {
|
|
|
341
406
|
declare function CMSFileUpload({ label, isRequired, fieldConfigItem, fieldProps, field, uploadImage, }: CMSFileUploadProps): react_jsx_runtime.JSX.Element;
|
|
342
407
|
|
|
343
408
|
export { AutoFormInputComponentProps, CMSFileUpload, cmsClientPlugin };
|
|
344
|
-
export type { CMSClientConfig, CMSFileUploadProps, CMSLocalization, CMSPluginOverrides, LoaderContext, RouteContext };
|
|
409
|
+
export type { CMSClientConfig, CMSClientHooks, CMSFileUploadProps, CMSLocalization, CMSPluginOverrides, LoaderContext, RouteContext };
|
|
@@ -12,23 +12,88 @@ import 'zod';
|
|
|
12
12
|
* Context passed to loader hooks
|
|
13
13
|
*/
|
|
14
14
|
interface LoaderContext {
|
|
15
|
+
/** Current route path */
|
|
15
16
|
path: string;
|
|
17
|
+
/** Route parameters (e.g., { typeSlug: "product", id: "123" }) */
|
|
16
18
|
params?: Record<string, string>;
|
|
19
|
+
/** Whether rendering on server (true) or client (false) */
|
|
17
20
|
isSSR: boolean;
|
|
21
|
+
/** Base URL for API calls */
|
|
18
22
|
apiBaseURL: string;
|
|
23
|
+
/** Path where the API is mounted */
|
|
19
24
|
apiBasePath: string;
|
|
25
|
+
/** Optional headers for the request */
|
|
20
26
|
headers?: Headers;
|
|
27
|
+
/** Additional context properties */
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Hooks for CMS client plugin
|
|
32
|
+
* All hooks are optional and allow consumers to customize behavior
|
|
33
|
+
*/
|
|
34
|
+
interface CMSClientHooks {
|
|
35
|
+
/**
|
|
36
|
+
* Called before loading the dashboard page. Return false to cancel loading.
|
|
37
|
+
* @param context - Loader context with path, params, etc.
|
|
38
|
+
*/
|
|
39
|
+
beforeLoadDashboard?: (context: LoaderContext) => Promise<boolean> | boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Called after the dashboard is loaded.
|
|
42
|
+
* @param context - Loader context
|
|
43
|
+
*/
|
|
44
|
+
afterLoadDashboard?: (context: LoaderContext) => Promise<void> | void;
|
|
45
|
+
/**
|
|
46
|
+
* Called before loading a content list page. Return false to cancel loading.
|
|
47
|
+
* @param typeSlug - The content type slug
|
|
48
|
+
* @param context - Loader context
|
|
49
|
+
*/
|
|
50
|
+
beforeLoadContentList?: (typeSlug: string, context: LoaderContext) => Promise<boolean> | boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Called after a content list is loaded.
|
|
53
|
+
* @param typeSlug - The content type slug
|
|
54
|
+
* @param context - Loader context
|
|
55
|
+
*/
|
|
56
|
+
afterLoadContentList?: (typeSlug: string, context: LoaderContext) => Promise<void> | void;
|
|
57
|
+
/**
|
|
58
|
+
* Called before loading the content editor page. Return false to cancel loading.
|
|
59
|
+
* @param typeSlug - The content type slug
|
|
60
|
+
* @param id - The content item ID (undefined for new items)
|
|
61
|
+
* @param context - Loader context
|
|
62
|
+
*/
|
|
63
|
+
beforeLoadContentEditor?: (typeSlug: string, id: string | undefined, context: LoaderContext) => Promise<boolean> | boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Called after the content editor is loaded.
|
|
66
|
+
* @param typeSlug - The content type slug
|
|
67
|
+
* @param id - The content item ID (undefined for new items)
|
|
68
|
+
* @param context - Loader context
|
|
69
|
+
*/
|
|
70
|
+
afterLoadContentEditor?: (typeSlug: string, id: string | undefined, context: LoaderContext) => Promise<void> | void;
|
|
71
|
+
/**
|
|
72
|
+
* Called when a loading error occurs.
|
|
73
|
+
* Use this for redirects on authorization failures.
|
|
74
|
+
* @param error - The error that occurred
|
|
75
|
+
* @param context - Loader context
|
|
76
|
+
*/
|
|
77
|
+
onLoadError?: (error: Error, context: LoaderContext) => Promise<void> | void;
|
|
21
78
|
}
|
|
22
79
|
/**
|
|
23
80
|
* Configuration for CMS client plugin
|
|
24
81
|
*/
|
|
25
82
|
interface CMSClientConfig {
|
|
83
|
+
/** Base URL for API calls (e.g., "http://localhost:3000") */
|
|
26
84
|
apiBaseURL: string;
|
|
85
|
+
/** Path where the API is mounted (e.g., "/api/data") */
|
|
27
86
|
apiBasePath: string;
|
|
87
|
+
/** Base URL of your site */
|
|
28
88
|
siteBaseURL: string;
|
|
89
|
+
/** Path where pages are mounted (e.g., "/pages") */
|
|
29
90
|
siteBasePath: string;
|
|
91
|
+
/** React Query client instance for caching */
|
|
30
92
|
queryClient: QueryClient;
|
|
93
|
+
/** Optional headers for SSR (e.g., forwarding cookies) */
|
|
31
94
|
headers?: Headers;
|
|
95
|
+
/** Optional hooks for customizing behavior (authorization, redirects, etc.) */
|
|
96
|
+
hooks?: CMSClientHooks;
|
|
32
97
|
}
|
|
33
98
|
/**
|
|
34
99
|
* CMS client plugin
|
|
@@ -341,4 +406,4 @@ interface CMSFileUploadProps extends AutoFormInputComponentProps {
|
|
|
341
406
|
declare function CMSFileUpload({ label, isRequired, fieldConfigItem, fieldProps, field, uploadImage, }: CMSFileUploadProps): react_jsx_runtime.JSX.Element;
|
|
342
407
|
|
|
343
408
|
export { AutoFormInputComponentProps, CMSFileUpload, cmsClientPlugin };
|
|
344
|
-
export type { CMSClientConfig, CMSFileUploadProps, CMSLocalization, CMSPluginOverrides, LoaderContext, RouteContext };
|
|
409
|
+
export type { CMSClientConfig, CMSClientHooks, CMSFileUploadProps, CMSLocalization, CMSPluginOverrides, LoaderContext, RouteContext };
|
package/package.json
CHANGED
|
@@ -6,18 +6,18 @@ import { PageHeader } from "../shared/page-header";
|
|
|
6
6
|
import { PageWrapper } from "../shared/page-wrapper";
|
|
7
7
|
import { BLOG_LOCALIZATION } from "../../localization";
|
|
8
8
|
import type { BlogPluginOverrides } from "../../overrides";
|
|
9
|
-
import { useRouteLifecycle } from "
|
|
9
|
+
import { useRouteLifecycle } from "@workspace/ui/hooks/use-route-lifecycle";
|
|
10
10
|
|
|
11
11
|
// Internal component with actual page content
|
|
12
12
|
export function EditPostPage({ slug }: { slug: string }) {
|
|
13
|
-
const
|
|
13
|
+
const overrides = usePluginOverrides<
|
|
14
14
|
BlogPluginOverrides,
|
|
15
15
|
Partial<BlogPluginOverrides>
|
|
16
16
|
>("blog", {
|
|
17
17
|
localization: BLOG_LOCALIZATION,
|
|
18
18
|
});
|
|
19
|
+
const { localization, navigate } = overrides;
|
|
19
20
|
const basePath = useBasePath();
|
|
20
|
-
const { navigate } = usePluginOverrides<BlogPluginOverrides>("blog");
|
|
21
21
|
|
|
22
22
|
// Call lifecycle hooks
|
|
23
23
|
useRouteLifecycle({
|
|
@@ -27,6 +27,7 @@ export function EditPostPage({ slug }: { slug: string }) {
|
|
|
27
27
|
params: { slug },
|
|
28
28
|
isSSR: typeof window === "undefined",
|
|
29
29
|
},
|
|
30
|
+
overrides,
|
|
30
31
|
beforeRenderHook: (overrides, context) => {
|
|
31
32
|
if (overrides.onBeforeEditPostPageRendered) {
|
|
32
33
|
return overrides.onBeforeEditPostPageRendered(slug, context);
|
|
@@ -9,16 +9,17 @@ import { useSuspensePosts } from "../../hooks/blog-hooks";
|
|
|
9
9
|
import { BLOG_LOCALIZATION } from "../../localization";
|
|
10
10
|
import { usePluginOverrides } from "@btst/stack/context";
|
|
11
11
|
import type { BlogPluginOverrides } from "../../overrides";
|
|
12
|
-
import { useRouteLifecycle } from "
|
|
12
|
+
import { useRouteLifecycle } from "@workspace/ui/hooks/use-route-lifecycle";
|
|
13
13
|
|
|
14
14
|
// Internal component with actual page content
|
|
15
15
|
export function HomePage({ published }: { published: boolean }) {
|
|
16
|
-
const
|
|
16
|
+
const overrides = usePluginOverrides<
|
|
17
17
|
BlogPluginOverrides,
|
|
18
18
|
Partial<BlogPluginOverrides>
|
|
19
19
|
>("blog", {
|
|
20
20
|
localization: BLOG_LOCALIZATION,
|
|
21
21
|
});
|
|
22
|
+
const { localization } = overrides;
|
|
22
23
|
|
|
23
24
|
// Call lifecycle hooks
|
|
24
25
|
useRouteLifecycle({
|
|
@@ -28,6 +29,7 @@ export function HomePage({ published }: { published: boolean }) {
|
|
|
28
29
|
isSSR: typeof window === "undefined",
|
|
29
30
|
published,
|
|
30
31
|
},
|
|
32
|
+
overrides,
|
|
31
33
|
beforeRenderHook: (overrides, context) => {
|
|
32
34
|
if (published && overrides.onBeforePostsPageRendered) {
|
|
33
35
|
return overrides.onBeforePostsPageRendered(context);
|
|
@@ -6,17 +6,17 @@ import { PageHeader } from "../shared/page-header";
|
|
|
6
6
|
import { PageWrapper } from "../shared/page-wrapper";
|
|
7
7
|
import type { BlogPluginOverrides } from "../../overrides";
|
|
8
8
|
import { BLOG_LOCALIZATION } from "../../localization";
|
|
9
|
-
import { useRouteLifecycle } from "
|
|
9
|
+
import { useRouteLifecycle } from "@workspace/ui/hooks/use-route-lifecycle";
|
|
10
10
|
|
|
11
11
|
// Internal component with actual page content
|
|
12
12
|
export function NewPostPage() {
|
|
13
|
-
const
|
|
13
|
+
const overrides = usePluginOverrides<
|
|
14
14
|
BlogPluginOverrides,
|
|
15
15
|
Partial<BlogPluginOverrides>
|
|
16
16
|
>("blog", {
|
|
17
17
|
localization: BLOG_LOCALIZATION,
|
|
18
18
|
});
|
|
19
|
-
const { navigate } =
|
|
19
|
+
const { localization, navigate } = overrides;
|
|
20
20
|
const basePath = useBasePath();
|
|
21
21
|
|
|
22
22
|
// Call lifecycle hooks
|
|
@@ -26,6 +26,7 @@ export function NewPostPage() {
|
|
|
26
26
|
path: "/blog/new",
|
|
27
27
|
isSSR: typeof window === "undefined",
|
|
28
28
|
},
|
|
29
|
+
overrides,
|
|
29
30
|
beforeRenderHook: (overrides, context) => {
|
|
30
31
|
if (overrides.onBeforeNewPostPageRendered) {
|
|
31
32
|
return overrides.onBeforeNewPostPageRendered(context);
|
|
@@ -17,19 +17,20 @@ import { BLOG_LOCALIZATION } from "../../localization";
|
|
|
17
17
|
import { PostNavigation } from "../shared/post-navigation";
|
|
18
18
|
import { RecentPostsCarousel } from "../shared/recent-posts-carousel";
|
|
19
19
|
import { Badge } from "@workspace/ui/components/badge";
|
|
20
|
-
import { useRouteLifecycle } from "
|
|
20
|
+
import { useRouteLifecycle } from "@workspace/ui/hooks/use-route-lifecycle";
|
|
21
21
|
import { OnThisPage, OnThisPageSelect } from "../shared/on-this-page";
|
|
22
22
|
import type { SerializedPost } from "../../../types";
|
|
23
23
|
|
|
24
24
|
// Internal component with actual page content
|
|
25
25
|
export function PostPage({ slug }: { slug: string }) {
|
|
26
|
-
const
|
|
26
|
+
const overrides = usePluginOverrides<
|
|
27
27
|
BlogPluginOverrides,
|
|
28
28
|
Partial<BlogPluginOverrides>
|
|
29
29
|
>("blog", {
|
|
30
30
|
Image: DefaultImage,
|
|
31
31
|
localization: BLOG_LOCALIZATION,
|
|
32
32
|
});
|
|
33
|
+
const { Image, localization } = overrides;
|
|
33
34
|
|
|
34
35
|
// Call lifecycle hooks
|
|
35
36
|
useRouteLifecycle({
|
|
@@ -39,6 +40,7 @@ export function PostPage({ slug }: { slug: string }) {
|
|
|
39
40
|
params: { slug },
|
|
40
41
|
isSSR: typeof window === "undefined",
|
|
41
42
|
},
|
|
43
|
+
overrides,
|
|
42
44
|
beforeRenderHook: (overrides, context) => {
|
|
43
45
|
if (overrides.onBeforePostPageRendered) {
|
|
44
46
|
return overrides.onBeforePostPageRendered(slug, context);
|
|
@@ -10,16 +10,17 @@ import { BLOG_LOCALIZATION } from "../../localization";
|
|
|
10
10
|
import { usePluginOverrides } from "@btst/stack/context";
|
|
11
11
|
import type { BlogPluginOverrides } from "../../overrides";
|
|
12
12
|
import { useTags } from "../../hooks/blog-hooks";
|
|
13
|
-
import { useRouteLifecycle } from "
|
|
13
|
+
import { useRouteLifecycle } from "@workspace/ui/hooks/use-route-lifecycle";
|
|
14
14
|
|
|
15
15
|
// Internal component with actual page content
|
|
16
16
|
export function TagPage({ tagSlug }: { tagSlug: string }) {
|
|
17
|
-
const
|
|
17
|
+
const overrides = usePluginOverrides<
|
|
18
18
|
BlogPluginOverrides,
|
|
19
19
|
Partial<BlogPluginOverrides>
|
|
20
20
|
>("blog", {
|
|
21
21
|
localization: BLOG_LOCALIZATION,
|
|
22
22
|
});
|
|
23
|
+
const { localization } = overrides;
|
|
23
24
|
|
|
24
25
|
// Call lifecycle hooks
|
|
25
26
|
useRouteLifecycle({
|
|
@@ -29,6 +30,7 @@ export function TagPage({ tagSlug }: { tagSlug: string }) {
|
|
|
29
30
|
params: { tagSlug },
|
|
30
31
|
isSSR: typeof window === "undefined",
|
|
31
32
|
},
|
|
33
|
+
overrides,
|
|
32
34
|
});
|
|
33
35
|
|
|
34
36
|
const { tags } = useTags();
|
|
@@ -386,15 +386,16 @@ function createTagLoader(tagSlug: string, config: BlogClientConfig) {
|
|
|
386
386
|
const tagsQuery = queries.tags.list();
|
|
387
387
|
await queryClient.prefetchQuery(tagsQuery);
|
|
388
388
|
|
|
389
|
-
if
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
389
|
+
// Check if there was an error in either query
|
|
390
|
+
const listState = queryClient.getQueryState(listQuery.queryKey);
|
|
391
|
+
const tagsState = queryClient.getQueryState(tagsQuery.queryKey);
|
|
392
|
+
const queryError = listState?.error || tagsState?.error;
|
|
393
|
+
if (queryError && hooks?.onLoadError) {
|
|
394
|
+
const error =
|
|
395
|
+
queryError instanceof Error
|
|
396
|
+
? queryError
|
|
397
|
+
: new Error(String(queryError));
|
|
398
|
+
await hooks.onLoadError(error, context);
|
|
398
399
|
}
|
|
399
400
|
} catch (error) {
|
|
400
401
|
if (hooks?.onLoadError) {
|
|
@@ -15,6 +15,7 @@ import { EmptyState } from "../shared/empty-state";
|
|
|
15
15
|
import { PageWrapper } from "../shared/page-wrapper";
|
|
16
16
|
import { EditorSkeleton } from "../loading/editor-skeleton";
|
|
17
17
|
import { CMS_LOCALIZATION } from "../../localization";
|
|
18
|
+
import { useRouteLifecycle } from "@workspace/ui/hooks/use-route-lifecycle";
|
|
18
19
|
|
|
19
20
|
interface ContentEditorPageProps {
|
|
20
21
|
typeSlug: string;
|
|
@@ -22,11 +23,28 @@ interface ContentEditorPageProps {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export function ContentEditorPage({ typeSlug, id }: ContentEditorPageProps) {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
const localization = { ...CMS_LOCALIZATION, ...
|
|
26
|
+
const overrides = usePluginOverrides<CMSPluginOverrides>("cms");
|
|
27
|
+
const { navigate } = overrides;
|
|
28
|
+
const localization = { ...CMS_LOCALIZATION, ...overrides.localization };
|
|
28
29
|
const basePath = useBasePath();
|
|
29
30
|
|
|
31
|
+
// Call lifecycle hooks for authorization
|
|
32
|
+
useRouteLifecycle({
|
|
33
|
+
routeName: "contentEditor",
|
|
34
|
+
context: {
|
|
35
|
+
path: id ? `/cms/${typeSlug}/${id}` : `/cms/${typeSlug}/new`,
|
|
36
|
+
params: id ? { typeSlug, id } : { typeSlug },
|
|
37
|
+
isSSR: typeof window === "undefined",
|
|
38
|
+
},
|
|
39
|
+
overrides,
|
|
40
|
+
beforeRenderHook: (overrides, context) => {
|
|
41
|
+
if (overrides.onBeforeEditorRendered) {
|
|
42
|
+
return overrides.onBeforeEditorRendered(typeSlug, id ?? null, context);
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
30
48
|
const { contentTypes } = useSuspenseContentTypes();
|
|
31
49
|
const contentType = contentTypes.find((ct) => ct.slug === typeSlug);
|
|
32
50
|
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
import { EmptyState } from "../shared/empty-state";
|
|
21
21
|
import { PageWrapper } from "../shared/page-wrapper";
|
|
22
22
|
import { CMS_LOCALIZATION } from "../../localization";
|
|
23
|
+
import { useRouteLifecycle } from "@workspace/ui/hooks/use-route-lifecycle";
|
|
23
24
|
import { toast } from "sonner";
|
|
24
25
|
|
|
25
26
|
interface ContentListPageProps {
|
|
@@ -27,14 +28,28 @@ interface ContentListPageProps {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export function ContentListPage({ typeSlug }: ContentListPageProps) {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
localization: customLocalization,
|
|
34
|
-
} = usePluginOverrides<CMSPluginOverrides>("cms");
|
|
35
|
-
const localization = { ...CMS_LOCALIZATION, ...customLocalization };
|
|
31
|
+
const overrides = usePluginOverrides<CMSPluginOverrides>("cms");
|
|
32
|
+
const { navigate, Link } = overrides;
|
|
33
|
+
const localization = { ...CMS_LOCALIZATION, ...overrides.localization };
|
|
36
34
|
const basePath = useBasePath();
|
|
37
35
|
|
|
36
|
+
// Call lifecycle hooks for authorization
|
|
37
|
+
useRouteLifecycle({
|
|
38
|
+
routeName: "contentList",
|
|
39
|
+
context: {
|
|
40
|
+
path: `/cms/${typeSlug}`,
|
|
41
|
+
params: { typeSlug },
|
|
42
|
+
isSSR: typeof window === "undefined",
|
|
43
|
+
},
|
|
44
|
+
overrides,
|
|
45
|
+
beforeRenderHook: (overrides, context) => {
|
|
46
|
+
if (overrides.onBeforeListRendered) {
|
|
47
|
+
return overrides.onBeforeListRendered(typeSlug, context);
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
38
53
|
const limit = 20;
|
|
39
54
|
|
|
40
55
|
const { contentTypes } = useSuspenseContentTypes();
|
|
@@ -13,12 +13,29 @@ import { useSuspenseContentTypes } from "../../hooks";
|
|
|
13
13
|
import { EmptyState } from "../shared/empty-state";
|
|
14
14
|
import { PageWrapper } from "../shared/page-wrapper";
|
|
15
15
|
import { CMS_LOCALIZATION } from "../../localization";
|
|
16
|
+
import { useRouteLifecycle } from "@workspace/ui/hooks/use-route-lifecycle";
|
|
16
17
|
|
|
17
18
|
export function DashboardPage() {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
const localization = { ...CMS_LOCALIZATION, ...
|
|
19
|
+
const overrides = usePluginOverrides<CMSPluginOverrides>("cms");
|
|
20
|
+
const { navigate } = overrides;
|
|
21
|
+
const localization = { ...CMS_LOCALIZATION, ...overrides.localization };
|
|
21
22
|
const basePath = useBasePath();
|
|
23
|
+
|
|
24
|
+
// Call lifecycle hooks for authorization
|
|
25
|
+
useRouteLifecycle({
|
|
26
|
+
routeName: "dashboard",
|
|
27
|
+
context: {
|
|
28
|
+
path: "/cms",
|
|
29
|
+
isSSR: typeof window === "undefined",
|
|
30
|
+
},
|
|
31
|
+
overrides,
|
|
32
|
+
beforeRenderHook: (overrides, context) => {
|
|
33
|
+
if (overrides.onBeforeDashboardRendered) {
|
|
34
|
+
return overrides.onBeforeDashboardRendered(context);
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
},
|
|
38
|
+
});
|
|
22
39
|
const { contentTypes } = useSuspenseContentTypes();
|
|
23
40
|
|
|
24
41
|
if (contentTypes.length === 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { cmsClientPlugin } from "./plugin";
|
|
2
|
-
export type { CMSClientConfig, LoaderContext } from "./plugin";
|
|
2
|
+
export type { CMSClientConfig, CMSClientHooks, LoaderContext } from "./plugin";
|
|
3
3
|
export type { CMSPluginOverrides, RouteContext } from "./overrides";
|
|
4
4
|
export type { CMSLocalization } from "./localization";
|
|
5
5
|
|