@jhits/plugin-blog 0.0.17 → 0.0.18
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/api/categories.d.ts.map +1 -1
- package/dist/api/categories.js +43 -12
- package/dist/api/handler.d.ts +1 -0
- package/dist/api/handler.d.ts.map +1 -1
- package/dist/api/handler.js +259 -32
- package/dist/hooks/useBlogs.d.ts +2 -0
- package/dist/hooks/useBlogs.d.ts.map +1 -1
- package/dist/hooks/useBlogs.js +10 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/lib/i18n.d.ts +14 -0
- package/dist/lib/i18n.d.ts.map +1 -0
- package/dist/lib/i18n.js +58 -0
- package/dist/lib/mappers/apiMapper.d.ts +18 -0
- package/dist/lib/mappers/apiMapper.d.ts.map +1 -1
- package/dist/lib/mappers/apiMapper.js +1 -0
- package/dist/state/reducer.d.ts.map +1 -1
- package/dist/state/reducer.js +11 -6
- package/dist/state/types.d.ts +5 -0
- package/dist/state/types.d.ts.map +1 -1
- package/dist/state/types.js +1 -0
- package/dist/types/post.d.ts +25 -0
- package/dist/types/post.d.ts.map +1 -1
- package/dist/utils/client.d.ts +2 -0
- package/dist/utils/client.d.ts.map +1 -1
- package/dist/utils/client.js +3 -1
- package/dist/views/CanvasEditor/CanvasEditorView.d.ts.map +1 -1
- package/dist/views/CanvasEditor/CanvasEditorView.js +130 -4
- package/dist/views/CanvasEditor/EditorHeader.d.ts +5 -1
- package/dist/views/CanvasEditor/EditorHeader.d.ts.map +1 -1
- package/dist/views/CanvasEditor/EditorHeader.js +23 -5
- package/dist/views/CanvasEditor/hooks/usePostLoader.d.ts +1 -1
- package/dist/views/CanvasEditor/hooks/usePostLoader.d.ts.map +1 -1
- package/dist/views/CanvasEditor/hooks/usePostLoader.js +14 -4
- package/dist/views/PostManager/LanguageFlags.d.ts +11 -0
- package/dist/views/PostManager/LanguageFlags.d.ts.map +1 -0
- package/dist/views/PostManager/LanguageFlags.js +60 -0
- package/dist/views/PostManager/PostCards.d.ts.map +1 -1
- package/dist/views/PostManager/PostCards.js +4 -1
- package/dist/views/PostManager/PostFilters.d.ts +4 -1
- package/dist/views/PostManager/PostFilters.d.ts.map +1 -1
- package/dist/views/PostManager/PostFilters.js +13 -3
- package/dist/views/PostManager/PostManagerView.d.ts.map +1 -1
- package/dist/views/PostManager/PostManagerView.js +24 -3
- package/dist/views/PostManager/PostTable.d.ts.map +1 -1
- package/dist/views/PostManager/PostTable.js +4 -1
- package/package.json +3 -3
- package/src/api/categories.ts +58 -11
- package/src/api/handler.ts +286 -31
- package/src/hooks/useBlogs.ts +12 -1
- package/src/index.tsx +7 -3
- package/src/lib/i18n.ts +78 -0
- package/src/lib/mappers/apiMapper.ts +20 -0
- package/src/state/reducer.ts +12 -6
- package/src/state/types.ts +5 -0
- package/src/types/post.ts +28 -0
- package/src/utils/client.ts +4 -0
- package/src/views/CanvasEditor/CanvasEditorView.tsx +164 -20
- package/src/views/CanvasEditor/EditorHeader.tsx +93 -18
- package/src/views/CanvasEditor/hooks/usePostLoader.ts +15 -4
- package/src/views/PostManager/LanguageFlags.tsx +136 -0
- package/src/views/PostManager/PostCards.tsx +22 -12
- package/src/views/PostManager/PostFilters.tsx +38 -1
- package/src/views/PostManager/PostManagerView.tsx +25 -2
- package/src/views/PostManager/PostTable.tsx +12 -1
|
@@ -39,6 +39,24 @@ export interface APIBlogDocument {
|
|
|
39
39
|
authorId?: string;
|
|
40
40
|
createdAt?: string | Date;
|
|
41
41
|
updatedAt?: string | Date;
|
|
42
|
+
languages?: {
|
|
43
|
+
[key: string]: {
|
|
44
|
+
blocks: Block[];
|
|
45
|
+
metadata: {
|
|
46
|
+
title?: string;
|
|
47
|
+
excerpt?: string;
|
|
48
|
+
featuredImage?: any;
|
|
49
|
+
categories?: string[];
|
|
50
|
+
tags?: string[];
|
|
51
|
+
seo?: any;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
availableLanguages?: string[];
|
|
56
|
+
lang?: string;
|
|
57
|
+
metadata?: {
|
|
58
|
+
lang?: string;
|
|
59
|
+
};
|
|
42
60
|
}
|
|
43
61
|
/**
|
|
44
62
|
* Convert API document to BlogPost format
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiMapper.d.ts","sourceRoot":"","sources":["../../../src/lib/mappers/apiMapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACnF,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE;QACJ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,OAAO,CAAC;KAGtB,CAAC;IACF,YAAY,CAAC,EAAE;QACX,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,eAAe,CAAC,EAAE;QACd,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;QAChC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,CAAC;IACF,GAAG,CAAC,EAAE;QACF,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"apiMapper.d.ts","sourceRoot":"","sources":["../../../src/lib/mappers/apiMapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../src/state/reducer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAsB,MAAM,SAAS,CAAC;AAqUxE;;;GAGG;AACH,wBAAgB,aAAa,CACzB,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,YAAY,GACrB,WAAW,
|
|
1
|
+
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../src/state/reducer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAsB,MAAM,SAAS,CAAC;AAqUxE;;;GAGG;AACH,wBAAgB,aAAa,CACzB,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,YAAY,GACrB,WAAW,CAyWb"}
|
package/dist/state/reducer.js
CHANGED
|
@@ -563,12 +563,12 @@ export function editorReducer(state, action) {
|
|
|
563
563
|
const post = action.payload;
|
|
564
564
|
return {
|
|
565
565
|
...state,
|
|
566
|
-
blocks: post.blocks,
|
|
567
|
-
title: post.title,
|
|
568
|
-
slug: post.slug,
|
|
569
|
-
seo: post.seo,
|
|
570
|
-
metadata: post.metadata,
|
|
571
|
-
status: post.publication
|
|
566
|
+
blocks: post.blocks || [],
|
|
567
|
+
title: post.title || '',
|
|
568
|
+
slug: post.slug || '',
|
|
569
|
+
seo: post.seo || {},
|
|
570
|
+
metadata: post.metadata || {},
|
|
571
|
+
status: post.publication?.status || 'draft',
|
|
572
572
|
postId: post.id,
|
|
573
573
|
isDirty: false,
|
|
574
574
|
selectedBlockId: null,
|
|
@@ -588,6 +588,11 @@ export function editorReducer(state, action) {
|
|
|
588
588
|
...state,
|
|
589
589
|
isDirty: true,
|
|
590
590
|
};
|
|
591
|
+
case 'SET_CURRENT_LANGUAGE':
|
|
592
|
+
return {
|
|
593
|
+
...state,
|
|
594
|
+
currentLanguage: action.payload,
|
|
595
|
+
};
|
|
591
596
|
case 'UNDO':
|
|
592
597
|
case 'REDO':
|
|
593
598
|
case 'SAVE_HISTORY':
|
package/dist/state/types.d.ts
CHANGED
|
@@ -31,6 +31,8 @@ export interface EditorState {
|
|
|
31
31
|
draggedBlockId: string | null;
|
|
32
32
|
/** Post ID (if editing existing post) */
|
|
33
33
|
postId: string | null;
|
|
34
|
+
/** Currently selected language for editing */
|
|
35
|
+
currentLanguage: string | null;
|
|
34
36
|
}
|
|
35
37
|
/**
|
|
36
38
|
* Editor Actions
|
|
@@ -102,6 +104,9 @@ export type EditorAction = {
|
|
|
102
104
|
type: 'MARK_CLEAN';
|
|
103
105
|
} | {
|
|
104
106
|
type: 'MARK_DIRTY';
|
|
107
|
+
} | {
|
|
108
|
+
type: 'SET_CURRENT_LANGUAGE';
|
|
109
|
+
payload: string;
|
|
105
110
|
} | {
|
|
106
111
|
type: 'UNDO';
|
|
107
112
|
} | {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/state/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEhF;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB,oCAAoC;IACpC,MAAM,EAAE,KAAK,EAAE,CAAC;IAEhB,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IAEd,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IAEb,mBAAmB;IACnB,GAAG,EAAE,WAAW,CAAC;IAEjB,oBAAoB;IACpB,QAAQ,EAAE,YAAY,CAAC;IAEvB,yBAAyB;IACzB,MAAM,EAAE,UAAU,CAAC;IAEnB,2CAA2C;IAC3C,OAAO,EAAE,OAAO,CAAC;IAEjB,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IAEnB,kCAAkC;IAClC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B,iCAAiC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B,yCAAyC;IACzC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/state/types.ts"],"names":[],"mappings":"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"}
|
package/dist/state/types.js
CHANGED
package/dist/types/post.d.ts
CHANGED
|
@@ -52,6 +52,8 @@ export interface PrivacySettings {
|
|
|
52
52
|
* Post Metadata
|
|
53
53
|
*/
|
|
54
54
|
export interface PostMetadata {
|
|
55
|
+
/** Language-specific title */
|
|
56
|
+
title?: string;
|
|
55
57
|
/** Featured image */
|
|
56
58
|
featuredImage?: {
|
|
57
59
|
id?: string;
|
|
@@ -94,6 +96,8 @@ export interface BlogPost {
|
|
|
94
96
|
publication: PublicationData;
|
|
95
97
|
/** Additional metadata */
|
|
96
98
|
metadata: PostMetadata;
|
|
99
|
+
/** Content per language (for multi-language posts) */
|
|
100
|
+
languages?: BlogPostLanguages;
|
|
97
101
|
/** Creation timestamp */
|
|
98
102
|
createdAt: string;
|
|
99
103
|
/** Last update timestamp */
|
|
@@ -116,6 +120,9 @@ export interface PostListItem {
|
|
|
116
120
|
authorId?: string;
|
|
117
121
|
updatedAt: string;
|
|
118
122
|
category?: string;
|
|
123
|
+
lang?: string;
|
|
124
|
+
availableLanguages?: string[];
|
|
125
|
+
languages?: BlogPostLanguages;
|
|
119
126
|
}
|
|
120
127
|
/**
|
|
121
128
|
* Post Filter Options
|
|
@@ -126,6 +133,7 @@ export interface PostFilterOptions {
|
|
|
126
133
|
tag?: string;
|
|
127
134
|
authorId?: string;
|
|
128
135
|
search?: string;
|
|
136
|
+
language?: string;
|
|
129
137
|
dateFrom?: string;
|
|
130
138
|
dateTo?: string;
|
|
131
139
|
limit?: number;
|
|
@@ -133,4 +141,21 @@ export interface PostFilterOptions {
|
|
|
133
141
|
sortBy?: 'date' | 'title' | 'updatedAt';
|
|
134
142
|
sortOrder?: 'asc' | 'desc';
|
|
135
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Blog post language content (blocks + metadata per language)
|
|
146
|
+
*/
|
|
147
|
+
export interface BlogPostLanguageContent {
|
|
148
|
+
blocks: Block[];
|
|
149
|
+
metadata: PostMetadata;
|
|
150
|
+
/** Per-language last update timestamp */
|
|
151
|
+
updatedAt?: string;
|
|
152
|
+
/** Per-language publication status */
|
|
153
|
+
status?: PostStatus;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Languages object storing content per language
|
|
157
|
+
*/
|
|
158
|
+
export interface BlogPostLanguages {
|
|
159
|
+
[key: string]: BlogPostLanguageContent;
|
|
160
|
+
}
|
|
136
161
|
//# sourceMappingURL=post.d.ts.map
|
package/dist/types/post.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../src/types/post.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../src/types/post.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/client.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export interface FetchBlogsOptions {
|
|
|
10
10
|
skip?: number;
|
|
11
11
|
/** Filter by status (published, draft, concept) */
|
|
12
12
|
status?: string;
|
|
13
|
+
/** Filter by language */
|
|
14
|
+
language?: string;
|
|
13
15
|
/** Whether to fetch all posts for admin (includes drafts) */
|
|
14
16
|
admin?: boolean;
|
|
15
17
|
/** API base URL (default: '/api/blogs') */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/utils/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAC9B,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC7B,0BAA0B;IAC1B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/utils/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAC9B,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC7B,0BAA0B;IAC1B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmD3F;AAED,MAAM,WAAW,gBAAgB;IAC7B,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkB5E"}
|
package/dist/utils/client.js
CHANGED
|
@@ -12,7 +12,7 @@ import { apiToBlogPost } from '../lib/mappers/apiMapper';
|
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
14
|
export async function fetchBlogs(options = {}) {
|
|
15
|
-
const { limit = 10, skip = 0, status, admin = false, apiBaseUrl = '/api/plugin-blog', } = options;
|
|
15
|
+
const { limit = 10, skip = 0, status, language, admin = false, apiBaseUrl = '/api/plugin-blog', } = options;
|
|
16
16
|
const params = new URLSearchParams();
|
|
17
17
|
if (limit)
|
|
18
18
|
params.set('limit', limit.toString());
|
|
@@ -20,6 +20,8 @@ export async function fetchBlogs(options = {}) {
|
|
|
20
20
|
params.set('skip', skip.toString());
|
|
21
21
|
if (status)
|
|
22
22
|
params.set('status', status);
|
|
23
|
+
if (language)
|
|
24
|
+
params.set('language', language);
|
|
23
25
|
if (admin)
|
|
24
26
|
params.set('admin', 'true');
|
|
25
27
|
const url = `${apiBaseUrl}?${params.toString()}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CanvasEditorView.d.ts","sourceRoot":"","sources":["../../../src/views/CanvasEditor/CanvasEditorView.tsx"],"names":[],"mappings":"AAaA,MAAM,WAAW,qBAAqB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uCAAuC;IACvC,gBAAgB,CAAC,EAAE;QACf,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACL;AAED,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"CanvasEditorView.d.ts","sourceRoot":"","sources":["../../../src/views/CanvasEditor/CanvasEditorView.tsx"],"names":[],"mappings":"AAaA,MAAM,WAAW,qBAAqB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uCAAuC;IACvC,gBAAgB,CAAC,EAAE;QACf,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACL;AAED,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,qBAAqB,2CAscpI"}
|
|
@@ -17,19 +17,145 @@ export function CanvasEditorView({ postId, darkMode, backgroundColors: propsBack
|
|
|
17
17
|
const [isPreviewMode, setIsPreviewMode] = useState(false);
|
|
18
18
|
const [isSaving, setIsSaving] = useState(false);
|
|
19
19
|
const [saveError, setSaveError] = useState(null);
|
|
20
|
+
// Language state for multilingual support
|
|
21
|
+
const [primaryLanguage, setPrimaryLanguage] = useState(locale || 'en');
|
|
22
|
+
const [isLoadingLanguage, setIsLoadingLanguage] = useState(true);
|
|
23
|
+
const [availableLanguages, setAvailableLanguages] = useState([locale || 'en']);
|
|
24
|
+
const [currentLanguage, setCurrentLanguage] = useState(locale || 'en');
|
|
20
25
|
// Get registered blocks
|
|
21
26
|
const registeredBlocks = useRegisteredBlocks();
|
|
22
27
|
// Hero block management
|
|
23
28
|
const { heroBlock, setHeroBlock, heroBlockDefinition } = useHeroBlock(state, registeredBlocks);
|
|
24
|
-
// Post loading
|
|
29
|
+
// Post loading - wait for language settings to be loaded first
|
|
25
30
|
const { isLoadingPost } = usePostLoader(postId, state.postId, (post) => {
|
|
26
31
|
helpers.loadPost(post);
|
|
32
|
+
// Don't reset current language when loading - preserve user's selection
|
|
33
|
+
// This allows switching to a new language even if no content exists yet
|
|
34
|
+
// Update available languages from post's languages object
|
|
35
|
+
if (post.languages && Object.keys(post.languages).length > 0) {
|
|
36
|
+
const langs = Object.keys(post.languages);
|
|
37
|
+
// Add current language to available if not already there
|
|
38
|
+
if (!langs.includes(currentLanguage)) {
|
|
39
|
+
langs.push(currentLanguage);
|
|
40
|
+
}
|
|
41
|
+
setAvailableLanguages(langs);
|
|
42
|
+
}
|
|
27
43
|
// After loading, ensure we're marked as clean
|
|
28
44
|
// Use setTimeout to ensure this runs after the reducer has processed LOAD_POST
|
|
29
45
|
setTimeout(() => {
|
|
30
46
|
dispatch({ type: 'MARK_CLEAN' });
|
|
31
47
|
}, 0);
|
|
32
|
-
}, () => setHeroBlock(null));
|
|
48
|
+
}, () => setHeroBlock(null), !isLoadingLanguage ? currentLanguage : undefined);
|
|
49
|
+
// Sync currentLanguage to editor state on mount so onSave always knows the active language
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
dispatch({ type: 'SET_CURRENT_LANGUAGE', payload: currentLanguage });
|
|
52
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps -- only on mount
|
|
53
|
+
// Fetch primary language from settings (simulated - in real app would come from config)
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const fetchLanguageSettings = async () => {
|
|
56
|
+
try {
|
|
57
|
+
// Use the locale prop as the initial language
|
|
58
|
+
// Only set this once on initial load, don't override if user already selected a language
|
|
59
|
+
if (!currentLanguage || currentLanguage === 'en') {
|
|
60
|
+
setPrimaryLanguage(locale || 'nl');
|
|
61
|
+
if (!availableLanguages.includes(locale || 'nl')) {
|
|
62
|
+
setAvailableLanguages([locale || 'nl']);
|
|
63
|
+
}
|
|
64
|
+
setCurrentLanguage(locale || 'nl');
|
|
65
|
+
dispatch({ type: 'SET_CURRENT_LANGUAGE', payload: locale || 'nl' });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error('Failed to fetch language settings:', error);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
setIsLoadingLanguage(false);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
fetchLanguageSettings();
|
|
76
|
+
}, []); // Empty dependency - only run once on mount
|
|
77
|
+
// Handle language change
|
|
78
|
+
const handleLanguageChange = async (newLanguage) => {
|
|
79
|
+
// Save current content first if dirty
|
|
80
|
+
if (state.isDirty) {
|
|
81
|
+
const confirmed = window.confirm('You have unsaved changes. Do you want to save them first?');
|
|
82
|
+
if (confirmed) {
|
|
83
|
+
await handleSave();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
setCurrentLanguage(newLanguage);
|
|
87
|
+
dispatch({ type: 'SET_CURRENT_LANGUAGE', payload: newLanguage });
|
|
88
|
+
// Reload with new language
|
|
89
|
+
if (postId) {
|
|
90
|
+
try {
|
|
91
|
+
const response = await fetch(`/api/plugin-blog/${postId}?language=${newLanguage}`);
|
|
92
|
+
if (response && response.ok) {
|
|
93
|
+
const apiDoc = await response.json();
|
|
94
|
+
// Manually update state instead of going through loadPost
|
|
95
|
+
// This avoids re-triggering the usePostLoader hook
|
|
96
|
+
const blocks = apiDoc.contentBlocks || apiDoc.blocks || [];
|
|
97
|
+
dispatch({ type: 'SET_TITLE', payload: apiDoc.title || '' });
|
|
98
|
+
// Replace all blocks
|
|
99
|
+
// First clear, then set new blocks via LOAD_POST-like behavior
|
|
100
|
+
// We use a custom dispatch to update blocks without resetting postId
|
|
101
|
+
dispatch({
|
|
102
|
+
type: 'LOAD_POST',
|
|
103
|
+
payload: {
|
|
104
|
+
id: state.postId || apiDoc._id || apiDoc.id,
|
|
105
|
+
title: apiDoc.title || '',
|
|
106
|
+
slug: apiDoc.slug || state.slug,
|
|
107
|
+
blocks: blocks,
|
|
108
|
+
seo: apiDoc.seo || {},
|
|
109
|
+
publication: {
|
|
110
|
+
status: apiDoc.publicationData?.status === 'concept' ? 'draft' : (apiDoc.publicationData?.status || state.status),
|
|
111
|
+
date: apiDoc.publicationData?.date,
|
|
112
|
+
authorId: apiDoc.authorId,
|
|
113
|
+
},
|
|
114
|
+
metadata: {
|
|
115
|
+
featuredImage: apiDoc.image ? {
|
|
116
|
+
id: apiDoc.image.id || apiDoc.image.src,
|
|
117
|
+
alt: apiDoc.image.alt,
|
|
118
|
+
isCustom: apiDoc.image.isCustom,
|
|
119
|
+
} : state.metadata?.featuredImage,
|
|
120
|
+
categories: apiDoc.categoryTags?.category ? [apiDoc.categoryTags.category] : [],
|
|
121
|
+
tags: apiDoc.categoryTags?.tags || [],
|
|
122
|
+
excerpt: apiDoc.summary || '',
|
|
123
|
+
lang: newLanguage,
|
|
124
|
+
},
|
|
125
|
+
languages: apiDoc.languages,
|
|
126
|
+
createdAt: apiDoc.createdAt || new Date().toISOString(),
|
|
127
|
+
updatedAt: apiDoc.updatedAt || new Date().toISOString(),
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
// Update available languages
|
|
131
|
+
if (apiDoc.availableLanguages) {
|
|
132
|
+
const langs = [...apiDoc.availableLanguages];
|
|
133
|
+
if (!langs.includes(newLanguage)) {
|
|
134
|
+
langs.push(newLanguage);
|
|
135
|
+
}
|
|
136
|
+
setAvailableLanguages(langs);
|
|
137
|
+
}
|
|
138
|
+
// Reset hero block so it re-initializes from new blocks
|
|
139
|
+
setHeroBlock(null);
|
|
140
|
+
setTimeout(() => {
|
|
141
|
+
dispatch({ type: 'MARK_CLEAN' });
|
|
142
|
+
}, 100);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
console.error('Failed to switch language:', error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
// Handle adding a new language
|
|
151
|
+
const handleAddLanguage = async (newLanguage) => {
|
|
152
|
+
if (availableLanguages.includes(newLanguage))
|
|
153
|
+
return;
|
|
154
|
+
// Add the new language to the list
|
|
155
|
+
setAvailableLanguages([...availableLanguages, newLanguage]);
|
|
156
|
+
// Switch to the new language (it will copy from primary language)
|
|
157
|
+
await handleLanguageChange(newLanguage);
|
|
158
|
+
};
|
|
33
159
|
// Track if we just loaded a post to prevent marking as dirty during cleanup
|
|
34
160
|
const justLoadedRef = useRef(false);
|
|
35
161
|
const previousIsLoadingRef = useRef(false);
|
|
@@ -199,7 +325,7 @@ export function CanvasEditorView({ postId, darkMode, backgroundColors: propsBack
|
|
|
199
325
|
data: { ...defaultData },
|
|
200
326
|
});
|
|
201
327
|
};
|
|
202
|
-
return (
|
|
328
|
+
return (_jsxs("div", { className: "h-full rounded-[2.5rem] w-full bg-dashboard-card text-dashboard-text flex flex-col font-sans transition-colors duration-300 overflow-hidden", children: [_jsx("header", { className: "overflow-visible flex-none shrink-0 z-10", children: _jsx(EditorHeader, { isLibraryOpen: isLibraryOpen, onLibraryToggle: () => setLibraryOpen(!isLibraryOpen), isPreviewMode: isPreviewMode, onPreviewToggle: () => setIsPreviewMode(!isPreviewMode), isSidebarOpen: isSidebarOpen, onSidebarToggle: () => setSidebarOpen(!isSidebarOpen), isSaving: isSaving, onSave: handleSave, onSaveError: (error) => {
|
|
203
329
|
// Format error message for display
|
|
204
330
|
if (error) {
|
|
205
331
|
let formattedError = error;
|
|
@@ -211,5 +337,5 @@ export function CanvasEditorView({ postId, darkMode, backgroundColors: propsBack
|
|
|
211
337
|
else {
|
|
212
338
|
setSaveError(null);
|
|
213
339
|
}
|
|
214
|
-
}, autoSaveEnabled: autoSaveEnabled, onAutoSaveToggle: setAutoSaveEnabled, isDirty: state.isDirty, autoSaveCountdown: countdown, autoSaveStatus: saveStatus }), _jsxs("div", { className: "flex flex-1 relative overflow-hidden min-h-0 flex-nowrap", children: [!isPreviewMode && (_jsx("aside", { className: `transition-all duration-500 ease-[cubic-bezier(0.4,0,0.2,1)] border-r border-dashboard-border bg-dashboard-sidebar overflow-y-auto overflow-x-hidden h-full ${isLibraryOpen ? 'w-72' : 'w-0 opacity-0 pointer-events-none'}`, children: _jsx(EditorLibrary, { registeredBlocks: registeredBlocks, onAddBlock: handleAddBlockAtBottom }) })), _jsx(EditorCanvas, { isPreviewMode: isPreviewMode, heroBlock: heroBlock, heroBlockDefinition: heroBlockDefinition, contentBlocks: contentBlocks, title: state.title, siteId: siteId, locale: locale, darkMode: effectiveDarkMode, backgroundColors: effectiveBackgroundColors, featuredImage: state.metadata.featuredImage, onTitleChange: (title) => dispatch({ type: 'SET_TITLE', payload: title }), onHeroBlockUpdate: handleHeroBlockUpdate, onHeroBlockDelete: handleHeroBlockDelete, onBlockAdd: (type, index, containerId) => helpers.addBlock(type, index, containerId), onBlockUpdate: (id, data) => helpers.updateBlock(id, data), onBlockDelete: (id) => helpers.deleteBlock(id), onBlockMove: (id, newIndex, containerId) => helpers.moveBlock(id, newIndex, containerId) }), !isPreviewMode && (_jsx("aside", { className: `transition-all duration-500 ease-[cubic-bezier(0.4,0,0.2,1)] border-l border-dashboard-border bg-dashboard-sidebar overflow-y-auto overflow-x-hidden h-full ${isSidebarOpen ? 'w-80' : 'w-0 opacity-0 pointer-events-none'}`, children: _jsx(EditorSidebar, { slug: state.slug, seo: state.seo, metadata: state.metadata, heroBlock: heroBlock, status: state.status, onSEOUpdate: (seo) => dispatch({ type: 'SET_SEO', payload: seo }), onMetadataUpdate: (metadata) => dispatch({ type: 'SET_METADATA', payload: metadata }) }) }))] })
|
|
340
|
+
}, autoSaveEnabled: autoSaveEnabled, onAutoSaveToggle: setAutoSaveEnabled, isDirty: state.isDirty, autoSaveCountdown: countdown, autoSaveStatus: saveStatus, languages: availableLanguages, currentLanguage: currentLanguage, onLanguageChange: handleLanguageChange, onAddLanguage: handleAddLanguage }) }), _jsx(ErrorBanner, { error: saveError, onDismiss: () => setSaveError(null) }), _jsx("main", { className: "flex flex-1 flex-col relative min-h-0 overflow-hidden", children: _jsxs("div", { className: "flex flex-1 relative overflow-hidden min-h-0 flex-nowrap", children: [!isPreviewMode && (_jsx("aside", { className: `transition-all duration-500 ease-[cubic-bezier(0.4,0,0.2,1)] border-r border-dashboard-border bg-dashboard-sidebar overflow-y-auto overflow-x-hidden h-full ${isLibraryOpen ? 'w-72' : 'w-0 opacity-0 pointer-events-none'}`, children: _jsx(EditorLibrary, { registeredBlocks: registeredBlocks, onAddBlock: handleAddBlockAtBottom }) })), _jsx(EditorCanvas, { isPreviewMode: isPreviewMode, heroBlock: heroBlock, heroBlockDefinition: heroBlockDefinition, contentBlocks: contentBlocks, title: state.title, siteId: siteId, locale: locale, darkMode: effectiveDarkMode, backgroundColors: effectiveBackgroundColors, featuredImage: state.metadata.featuredImage, onTitleChange: (title) => dispatch({ type: 'SET_TITLE', payload: title }), onHeroBlockUpdate: handleHeroBlockUpdate, onHeroBlockDelete: handleHeroBlockDelete, onBlockAdd: (type, index, containerId) => helpers.addBlock(type, index, containerId), onBlockUpdate: (id, data) => helpers.updateBlock(id, data), onBlockDelete: (id) => helpers.deleteBlock(id), onBlockMove: (id, newIndex, containerId) => helpers.moveBlock(id, newIndex, containerId) }), !isPreviewMode && (_jsx("aside", { className: `transition-all duration-500 ease-[cubic-bezier(0.4,0,0.2,1)] border-l border-dashboard-border bg-dashboard-sidebar overflow-y-auto overflow-x-hidden h-full ${isSidebarOpen ? 'w-80' : 'w-0 opacity-0 pointer-events-none'}`, children: _jsx(EditorSidebar, { slug: state.slug, seo: state.seo, metadata: state.metadata, heroBlock: heroBlock, status: state.status, onSEOUpdate: (seo) => dispatch({ type: 'SET_SEO', payload: seo }), onMetadataUpdate: (metadata) => dispatch({ type: 'SET_METADATA', payload: metadata }) }) }))] }) })] }));
|
|
215
341
|
}
|
|
@@ -13,6 +13,10 @@ export interface EditorHeaderProps {
|
|
|
13
13
|
isDirty?: boolean;
|
|
14
14
|
autoSaveCountdown?: number | null;
|
|
15
15
|
autoSaveStatus?: 'idle' | 'saving' | 'saved' | 'error';
|
|
16
|
+
languages?: string[];
|
|
17
|
+
currentLanguage?: string;
|
|
18
|
+
onLanguageChange?: (language: string) => void;
|
|
19
|
+
onAddLanguage?: (language: string) => void;
|
|
16
20
|
}
|
|
17
|
-
export declare function EditorHeader({ isLibraryOpen, onLibraryToggle, isPreviewMode, onPreviewToggle, isSidebarOpen, onSidebarToggle, isSaving, onSave, onSaveError, autoSaveEnabled, onAutoSaveToggle, isDirty, autoSaveCountdown, autoSaveStatus, }: EditorHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare function EditorHeader({ isLibraryOpen, onLibraryToggle, isPreviewMode, onPreviewToggle, isSidebarOpen, onSidebarToggle, isSaving, onSave, onSaveError, autoSaveEnabled, onAutoSaveToggle, isDirty, autoSaveCountdown, autoSaveStatus, languages, currentLanguage, onLanguageChange, onAddLanguage, }: EditorHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
18
22
|
//# sourceMappingURL=EditorHeader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorHeader.d.ts","sourceRoot":"","sources":["../../../src/views/CanvasEditor/EditorHeader.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAC9B,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"EditorHeader.d.ts","sourceRoot":"","sources":["../../../src/views/CanvasEditor/EditorHeader.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAC9B,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;IACvD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C;AAED,wBAAgB,YAAY,CAAC,EACzB,aAAa,EACb,eAAe,EACf,aAAa,EACb,eAAe,EACf,aAAa,EACb,eAAe,EACf,QAAQ,EACR,MAAM,EACN,WAAW,EACX,eAAuB,EACvB,gBAAgB,EAChB,OAAe,EACf,iBAAwB,EACxB,cAAuB,EACvB,SAAc,EACd,eAAsB,EACtB,gBAAgB,EAChB,aAAa,GAChB,EAAE,iBAAiB,2CAsSnB"}
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState } from 'react';
|
|
4
|
-
import { ArrowLeft, Library, Settings2, Clock, Edit, Eye } from 'lucide-react';
|
|
4
|
+
import { ArrowLeft, Library, Settings2, Clock, Edit, Eye, Globe, ChevronDown } from 'lucide-react';
|
|
5
5
|
import { useEditor } from '../../state/EditorContext';
|
|
6
6
|
import { SaveConfirmationModal } from './SaveConfirmationModal';
|
|
7
|
-
export function EditorHeader({ isLibraryOpen, onLibraryToggle, isPreviewMode, onPreviewToggle, isSidebarOpen, onSidebarToggle, isSaving, onSave, onSaveError, autoSaveEnabled = false, onAutoSaveToggle, isDirty = false, autoSaveCountdown = null, autoSaveStatus = 'idle', }) {
|
|
7
|
+
export function EditorHeader({ isLibraryOpen, onLibraryToggle, isPreviewMode, onPreviewToggle, isSidebarOpen, onSidebarToggle, isSaving, onSave, onSaveError, autoSaveEnabled = false, onAutoSaveToggle, isDirty = false, autoSaveCountdown = null, autoSaveStatus = 'idle', languages = [], currentLanguage = 'en', onLanguageChange, onAddLanguage, }) {
|
|
8
8
|
const { state, dispatch } = useEditor();
|
|
9
9
|
const [showConfirmModal, setShowConfirmModal] = useState(false);
|
|
10
10
|
const [saveAsDraft, setSaveAsDraft] = useState(false);
|
|
11
11
|
const [saveError, setSaveError] = useState(null);
|
|
12
|
+
const [showLanguageDropdown, setShowLanguageDropdown] = useState(false);
|
|
13
|
+
const languageLabels = {
|
|
14
|
+
en: 'English',
|
|
15
|
+
nl: 'Nederlands',
|
|
16
|
+
sv: 'Svenska',
|
|
17
|
+
de: 'Deutsch',
|
|
18
|
+
fr: 'Français',
|
|
19
|
+
es: 'Español',
|
|
20
|
+
};
|
|
21
|
+
const availableToAdd = ['en', 'nl', 'sv', 'de', 'fr', 'es'].filter(lang => !languages.includes(lang));
|
|
12
22
|
const handleSaveDraftClick = () => {
|
|
13
23
|
setSaveAsDraft(true);
|
|
14
24
|
setSaveError(null); // Clear any previous errors
|
|
@@ -65,7 +75,7 @@ export function EditorHeader({ isLibraryOpen, onLibraryToggle, isPreviewMode, on
|
|
|
65
75
|
throw error;
|
|
66
76
|
}
|
|
67
77
|
};
|
|
68
|
-
return (_jsxs("
|
|
78
|
+
return (_jsxs("div", { className: "flex items-center justify-between px-6 py-3 bg-dashboard-sidebar backdrop-blur-md border-b border-dashboard-border flex-none shrink-0", children: [_jsxs("div", { className: "flex items-center gap-6", children: [_jsx("button", { onClick: () => {
|
|
69
79
|
if (isDirty) {
|
|
70
80
|
const confirmed = window.confirm('You have unsaved changes. Are you sure you want to leave? Your changes will be lost.');
|
|
71
81
|
if (!confirmed) {
|
|
@@ -73,7 +83,15 @@ export function EditorHeader({ isLibraryOpen, onLibraryToggle, isPreviewMode, on
|
|
|
73
83
|
}
|
|
74
84
|
}
|
|
75
85
|
window.location.href = '/dashboard/blog';
|
|
76
|
-
}, className: "text-neutral-500 dark:text-neutral-400 hover:text-neutral-950 dark:hover:text-white transition-colors", children: _jsx(ArrowLeft, { size: 20, strokeWidth: 1.5 }) }), _jsx("div", { className: "h-4 w-[1px] bg-neutral-300 dark:border-neutral-700" }), _jsxs("button", { onClick: onLibraryToggle, className: `flex items-center gap-2 text-[10px] uppercase tracking-widest font-black transition-all ${isLibraryOpen ? 'text-dashboard-text' : 'text-neutral-500 dark:text-neutral-400'}`, children: [_jsx(Library, { size: 16, strokeWidth: 1.5 }), "Library"] })
|
|
86
|
+
}, className: "text-neutral-500 dark:text-neutral-400 hover:text-neutral-950 dark:hover:text-white transition-colors", children: _jsx(ArrowLeft, { size: 20, strokeWidth: 1.5 }) }), _jsx("div", { className: "h-4 w-[1px] bg-neutral-300 dark:border-neutral-700" }), _jsxs("button", { onClick: onLibraryToggle, className: `flex items-center gap-2 text-[10px] uppercase tracking-widest font-black transition-all ${isLibraryOpen ? 'text-dashboard-text' : 'text-neutral-500 dark:text-neutral-400'}`, children: [_jsx(Library, { size: 16, strokeWidth: 1.5 }), "Library"] }), languages.length > 0 && onLanguageChange && (_jsxs(_Fragment, { children: [_jsx("div", { className: "h-4 w-[1px] bg-neutral-300 dark:border-neutral-700" }), _jsxs("div", { className: "relative", children: [_jsxs("button", { onClick: () => setShowLanguageDropdown(!showLanguageDropdown), className: "flex items-center gap-2 px-3 py-2 text-[10px] uppercase tracking-widest font-bold bg-dashboard-card border border-dashboard-border rounded-lg text-neutral-600 dark:text-neutral-400 hover:text-dashboard-text hover:border-primary/50 transition-all shadow-sm", children: [_jsx(Globe, { size: 14, strokeWidth: 1.5 }), _jsx("span", { children: languageLabels[currentLanguage] || currentLanguage.toUpperCase() }), _jsx(ChevronDown, { size: 12, className: `transition-transform ${showLanguageDropdown ? 'rotate-180' : ''}` })] }), showLanguageDropdown && (_jsxs("div", { className: "absolute top-full left-0 mt-2 py-1 bg-dashboard-card border border-dashboard-border rounded-lg shadow-xl z-[9999] min-w-[160px] overflow-hidden", children: [_jsx("div", { className: "px-3 py-2 text-[9px] text-neutral-500 uppercase tracking-wider border-b border-dashboard-border", children: "Beschikbare Talen" }), languages.map(lang => (_jsx("button", { onClick: () => {
|
|
87
|
+
onLanguageChange(lang);
|
|
88
|
+
setShowLanguageDropdown(false);
|
|
89
|
+
}, className: `w-full text-left px-3 py-2 text-[10px] uppercase tracking-wider transition-colors ${lang === currentLanguage
|
|
90
|
+
? 'bg-primary/10 text-primary font-bold'
|
|
91
|
+
: 'text-neutral-600 dark:text-neutral-400 hover:bg-dashboard-bg hover:text-dashboard-text'}`, children: languageLabels[lang] || lang.toUpperCase() }, lang))), availableToAdd.length > 0 && onAddLanguage && (_jsxs(_Fragment, { children: [_jsx("div", { className: "my-1 border-t border-dashboard-border" }), _jsx("div", { className: "px-3 py-1 text-[9px] text-neutral-500 uppercase tracking-wider", children: "Add Language" }), availableToAdd.slice(0, 3).map(lang => (_jsxs("button", { onClick: () => {
|
|
92
|
+
onAddLanguage(lang);
|
|
93
|
+
setShowLanguageDropdown(false);
|
|
94
|
+
}, className: "w-full text-left px-3 py-2 text-[10px] uppercase tracking-wider text-neutral-600 dark:text-neutral-400 hover:bg-dashboard-bg hover:text-dashboard-text transition-colors", children: ["+ ", languageLabels[lang] || lang.toUpperCase()] }, lang)))] }))] }))] })] }))] }), _jsxs("div", { className: "flex items-center gap-4", children: [onAutoSaveToggle && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { onClick: () => onAutoSaveToggle(!autoSaveEnabled), className: `relative flex items-center gap-2 px-3 py-1.5 rounded-full text-[10px] uppercase tracking-widest font-bold transition-all ${autoSaveEnabled
|
|
77
95
|
? 'bg-primary/20 text-primary border border-primary/30'
|
|
78
96
|
: 'bg-dashboard-bg text-neutral-600 dark:text-neutral-400 border border-dashboard-border hover:text-neutral-950 dark:hover:text-white'}`, title: autoSaveEnabled ? 'Auto-save enabled (saves after 10s of inactivity)' : 'Click to enable auto-save', children: [_jsx(Clock, { size: 12, className: autoSaveEnabled && autoSaveStatus !== 'saving' ? 'animate-pulse' : '' }), _jsx("span", { children: "Auto-save" }), _jsx("span", { className: `ml-1 text-[9px] ${autoSaveEnabled ? 'text-primary' : 'text-neutral-500 dark:text-neutral-400'}`, children: autoSaveEnabled ? 'ON' : 'OFF' }), autoSaveEnabled && isDirty && (_jsxs("span", { className: "ml-1.5 text-[9px] font-bold tabular-nums", children: [autoSaveStatus === 'saving' && (_jsx("span", { className: "text-primary animate-pulse", children: "Saving..." })), autoSaveStatus === 'saved' && (_jsx("span", { className: "text-green-500 dark:text-green-400", children: "Saved!" })), autoSaveStatus === 'error' && (_jsx("span", { className: "text-red-500 dark:text-red-400", children: "Error" })), autoSaveStatus === 'idle' && autoSaveCountdown !== null && (_jsxs("span", { className: "text-primary/70", children: [autoSaveCountdown, "s"] }))] }))] }), isDirty && !autoSaveEnabled && (_jsx("span", { className: "text-[10px] text-amber-500 dark:text-amber-400 font-bold uppercase tracking-widest animate-pulse", children: "Unsaved" }))] })), _jsxs("div", { className: "flex items-center bg-dashboard-bg border border-dashboard-border rounded-full p-1 gap-1", children: [_jsxs("button", { onClick: () => {
|
|
79
97
|
if (isPreviewMode) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BlogPost } from '../../../types/post';
|
|
2
|
-
export declare function usePostLoader(postId: string | undefined, currentPostId: string | null, loadPost: (post: BlogPost) => void, resetHeroBlock: () => void): {
|
|
2
|
+
export declare function usePostLoader(postId: string | undefined, currentPostId: string | null, loadPost: (post: BlogPost) => void, resetHeroBlock: () => void, language?: string): {
|
|
3
3
|
isLoadingPost: boolean;
|
|
4
4
|
};
|
|
5
5
|
//# sourceMappingURL=usePostLoader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePostLoader.d.ts","sourceRoot":"","sources":["../../../../src/views/CanvasEditor/hooks/usePostLoader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,wBAAgB,aAAa,CACzB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,EAClC,cAAc,EAAE,MAAM,IAAI;;
|
|
1
|
+
{"version":3,"file":"usePostLoader.d.ts","sourceRoot":"","sources":["../../../../src/views/CanvasEditor/hooks/usePostLoader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,wBAAgB,aAAa,CACzB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,EAClC,cAAc,EAAE,MAAM,IAAI,EAC1B,QAAQ,CAAC,EAAE,MAAM;;EAwCpB"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
1
|
+
import { useEffect, useState, useRef } from 'react';
|
|
2
2
|
import { apiToBlogPost } from '../../../lib/mappers/apiMapper';
|
|
3
|
-
export function usePostLoader(postId, currentPostId, loadPost, resetHeroBlock) {
|
|
3
|
+
export function usePostLoader(postId, currentPostId, loadPost, resetHeroBlock, language) {
|
|
4
4
|
const [isLoadingPost, setIsLoadingPost] = useState(false);
|
|
5
|
+
// Use a ref to track language so changes don't re-trigger initial load
|
|
6
|
+
const languageRef = useRef(language);
|
|
7
|
+
languageRef.current = language;
|
|
5
8
|
useEffect(() => {
|
|
6
9
|
if (postId && !currentPostId) {
|
|
7
10
|
const loadPostData = async () => {
|
|
@@ -9,7 +12,11 @@ export function usePostLoader(postId, currentPostId, loadPost, resetHeroBlock) {
|
|
|
9
12
|
setIsLoadingPost(true);
|
|
10
13
|
// Reset hero block before loading new post so it gets re-initialized from the new post's blocks
|
|
11
14
|
resetHeroBlock();
|
|
12
|
-
const
|
|
15
|
+
const lang = languageRef.current;
|
|
16
|
+
const url = lang
|
|
17
|
+
? `/api/plugin-blog/${postId}?language=${lang}`
|
|
18
|
+
: `/api/plugin-blog/${postId}`;
|
|
19
|
+
const response = await fetch(url);
|
|
13
20
|
if (!response.ok) {
|
|
14
21
|
throw new Error('Failed to load post');
|
|
15
22
|
}
|
|
@@ -27,6 +34,9 @@ export function usePostLoader(postId, currentPostId, loadPost, resetHeroBlock) {
|
|
|
27
34
|
};
|
|
28
35
|
loadPostData();
|
|
29
36
|
}
|
|
30
|
-
|
|
37
|
+
// Only re-run on initial load (postId / currentPostId change), NOT on language change
|
|
38
|
+
// Language switching is handled separately by handleLanguageChange
|
|
39
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
40
|
+
}, [postId, currentPostId]);
|
|
31
41
|
return { isLoadingPost };
|
|
32
42
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language Flags Component
|
|
3
|
+
* Displays interactive language flags with custom tooltips
|
|
4
|
+
*/
|
|
5
|
+
import { PostListItem } from '../../types/post';
|
|
6
|
+
interface LanguageFlagsProps {
|
|
7
|
+
post: PostListItem;
|
|
8
|
+
}
|
|
9
|
+
export declare function LanguageFlags({ post }: LanguageFlagsProps): import("react/jsx-runtime").JSX.Element | null;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=LanguageFlags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LanguageFlags.d.ts","sourceRoot":"","sources":["../../../src/views/PostManager/LanguageFlags.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,UAAU,kBAAkB;IACxB,IAAI,EAAE,YAAY,CAAC;CACtB;AAwBD,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,kBAAkB,kDAiGzD"}
|