Skip to content

Commit de70132

Browse files
committed
feat(dashboard): integrate DictionaryLoaderDashboard into TranslateDashboardPage and enhance TranslateDashboard with edited content handling
1 parent a71d47a commit de70132

File tree

4 files changed

+71
-25
lines changed

4 files changed

+71
-25
lines changed

apps/website/src/app/[locale]/(dashboard)/dashboard/(editor)/(content)/translate/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { DictionaryLoaderDashboard } from '@components/Dashboard/Editor/DictionaryLoaderDashboard';
12
import { TranslateDashboard } from '@components/Dashboard/TranslateDashboard';
23
import type { NextPageIntlayer } from 'next-intlayer';
34
import { IntlayerServerProvider } from 'next-intlayer/server';
@@ -10,6 +11,7 @@ const TranslateDashboardPage: NextPageIntlayer = async ({ params }) => {
1011
return (
1112
<IntlayerServerProvider locale={locale}>
1213
<div className="relative flex flex-1 flex-col items-center">
14+
<DictionaryLoaderDashboard />
1315
<TranslateDashboard />
1416
</div>
1517
</IntlayerServerProvider>

apps/website/src/components/Dashboard/TranslateDashboard/index.tsx

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
'use client';
22

3-
import { getEmptyNode, getLocaleName, getNodeType } from '@intlayer/core';
3+
import {
4+
getContentNodeByKeyPath,
5+
getEmptyNode,
6+
getLocaleName,
7+
getNodeType,
8+
} from '@intlayer/core';
49
import {
510
Button,
611
KeyPathBreadcrumb,
@@ -15,16 +20,15 @@ import {
1520
useInfiniteGetDictionaries,
1621
useSearch,
1722
} from '@intlayer/design-system/hooks';
18-
import { useConfiguration, useEditedContent } from '@intlayer/editor-react';
1923
import {
20-
type Dictionary,
21-
type KeyPath,
22-
type LocalesValues,
23-
NodeType,
24-
} from '@intlayer/types';
24+
useConfiguration,
25+
useDictionariesRecordActions,
26+
useEditedContent,
27+
} from '@intlayer/editor-react';
28+
import { type Dictionary, type LocalesValues, NodeType } from '@intlayer/types';
2529
import { Plus } from 'lucide-react';
2630
import { useIntlayer, useLocale } from 'next-intlayer';
27-
import { type FC, Suspense, useMemo, useState } from 'react';
31+
import { type FC, Suspense, useEffect, useMemo, useState } from 'react';
2832
import { GroupedVirtuoso } from 'react-virtuoso';
2933
import {
3034
type FlattenedDictionaryNode,
@@ -36,16 +40,23 @@ const TranslateRow: FC<{
3640
node: FlattenedDictionaryNode;
3741
selectedLocales: LocalesValues[];
3842
}> = ({ node, selectedLocales }) => {
39-
const { dictionary, keyPath, content, nodeType } = node;
40-
const { addEditedContent } = useEditedContent();
43+
const { dictionary, keyPath, content: originalContent, nodeType } = node;
44+
const { editedContent, addEditedContent } = useEditedContent();
4145
const configuration = useConfiguration();
4246
const { defaultLocale } = configuration.internationalization;
4347
const { addTranslation } = useIntlayer('dictionary-list');
4448

49+
// Use edited content if available, otherwise fall back to original content from node
50+
const editedDictionaryContent = editedContent?.[dictionary.localId!]?.content;
51+
const content =
52+
typeof editedDictionaryContent === 'undefined'
53+
? originalContent
54+
: getContentNodeByKeyPath(editedDictionaryContent, keyPath);
55+
4556
const isMultilingual =
4657
nodeType === NodeType.Translation ||
4758
(nodeType === NodeType.Insertion &&
48-
getNodeType((content as any).content) === NodeType.Translation);
59+
getNodeType((originalContent as any).content) === NodeType.Translation);
4960

5061
if (isMultilingual) {
5162
return (
@@ -81,16 +92,18 @@ const TranslateRow: FC<{
8192
contentMap[Object.keys(contentMap)[0]];
8293

8394
// Create an empty node based on the reference structure
84-
const newContent = getEmptyNode(referenceContent);
85-
const newKeyPath = [
86-
...keyPath,
87-
{ type: nodeType, key: locale },
88-
];
95+
const newContent = {
96+
...((editedContent as Record<string, any>) ?? {}),
97+
[nodeType]: {
98+
...contentMap,
99+
[locale]: getEmptyNode(referenceContent),
100+
},
101+
};
89102

90103
addEditedContent(
91104
dictionary.localId!,
92105
newContent,
93-
newKeyPath as KeyPath[]
106+
keyPath
94107
);
95108
}}
96109
>
@@ -105,7 +118,9 @@ const TranslateRow: FC<{
105118
<TextEditor
106119
section={translationContent}
107120
keyPath={[...keyPath, { type: nodeType, key: locale } as any]}
108-
dictionary={dictionary}
121+
dictionary={
122+
editedContent?.[dictionary.localId!] ?? dictionary
123+
}
109124
/>
110125
</div>
111126
);
@@ -141,20 +156,37 @@ const TranslateDashboardList: FC = () => {
141156
const { setSearch } = useSearch({});
142157
const { locale: currentLocale } = useLocale();
143158
const [search, setInternalSearch] = useState('');
159+
const { setLocaleDictionaries } = useDictionariesRecordActions() ?? {};
144160

145161
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isPending } =
146162
useInfiniteGetDictionaries({ search, pageSize: 3 });
147163

148164
const { selectedLocales } = useLocaleSwitcherContent();
149165

150-
const allLoadedDictionaries: Record<string, Dictionary> = {};
151-
data?.pages.forEach((page: any) => {
152-
(page.data as Dictionary[]).forEach((dict) => {
153-
if (dict.localId) {
154-
allLoadedDictionaries[dict.localId] = dict;
155-
}
166+
const allLoadedDictionaries: Record<string, Dictionary> = useMemo(() => {
167+
const result: Record<string, Dictionary> = {};
168+
data?.pages.forEach((page: any) => {
169+
(page.data as Dictionary[]).forEach((dict) => {
170+
if (dict.localId) {
171+
result[dict.localId] = dict;
172+
}
173+
});
156174
});
157-
});
175+
return result;
176+
}, [data?.pages]);
177+
178+
// Populate localeDictionaries context so addEditedContent can work properly
179+
useEffect(() => {
180+
if (
181+
setLocaleDictionaries &&
182+
Object.keys(allLoadedDictionaries).length > 0
183+
) {
184+
setLocaleDictionaries((prev) => ({
185+
...prev,
186+
...allLoadedDictionaries,
187+
}));
188+
}
189+
}, [allLoadedDictionaries, setLocaleDictionaries]);
158190

159191
const flattenedNodes: FlattenedDictionaryNode[] =
160192
data?.pages.flatMap((page: any) =>

packages/@intlayer/core/src/dictionaryManipulator/editDictionaryByKeyPath.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ export const editDictionaryByKeyPath = (
77
keyPath: KeyPath[],
88
newValue: ContentNode
99
): ContentNode => {
10+
console.log('editDictionaryByKeyPath');
11+
console.dir(
12+
{
13+
dictionaryContent,
14+
keyPath,
15+
newValue,
16+
},
17+
{ depth: null }
18+
);
1019
let currentValue: any = dictionaryContent;
1120
let parentValue: any = null;
1221
let lastKeys: LastKeyType[] = [];

packages/@intlayer/editor-react/src/EditedContentContext.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ export const EditedContentProvider: FC<PropsWithChildren> = ({ children }) => {
148148
overwrite: boolean = true
149149
) => {
150150
setEditedContentState((prev) => {
151+
console.log('addEditedContent from useEditedContent');
152+
console.dir({ localeDictionaries, localDictionaryId }, { depth: null });
153+
151154
// Get the starting content: edited version if available, otherwise a deep copy of the original
152155
const originalContent = localeDictionaries[localDictionaryId]?.content;
153156
const currentContent = structuredClone(

0 commit comments

Comments
 (0)