@parhelia/localization 0.1.11873 → 0.1.11955
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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -0
- package/dist/services/translationService.d.ts +19 -1
- package/dist/services/translationService.d.ts.map +1 -1
- package/dist/services/translationService.js +26 -2
- package/dist/settings/TranslationServicesPanel.d.ts +7 -0
- package/dist/settings/TranslationServicesPanel.d.ts.map +1 -0
- package/dist/settings/TranslationServicesPanel.js +237 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ export { TranslationManagement } from "./translation-center/TranslationManagemen
|
|
|
32
32
|
export { RecentTranslations } from "./translation-center/RecentTranslations";
|
|
33
33
|
export { BatchTranslationView } from "./translation-center/BatchTranslationView";
|
|
34
34
|
export { LocalizationSetupStep } from "./setup/LocalizationSetupStep";
|
|
35
|
+
export { TranslationServicesPanel } from "./settings/TranslationServicesPanel";
|
|
35
36
|
export type { LocalizeItemCommand, LocalizeItemCommandContext, LocalizeItemCommandData } from "./LocalizeItemCommand";
|
|
36
37
|
export { defaultTranslateAll, generateBatchId, performDefaultTranslation, type StartedTranslation, type TranslationResult } from "./LocalizeItemUtils";
|
|
37
38
|
export * from "./steps/types";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAatD,OAAO,EACL,mBAAmB,EAGpB,MAAM,gBAAgB,CAAC;AAUxB,QAAA,MAAM,wCAAwC;;;;;;;;;;;;8BAalB,qBAAqB;;CAchD,CAAC;AAEF,QAAA,MAAM,4CAA4C;;;;;;;CAUjD,CAAC;AAkCF,OAAO,EAAE,wCAAwC,EAAE,4CAA4C,EAAE,CAAC;AAClG,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,YAAY,EACV,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,yBAAyB,EACzB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,YAAY,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEhF,MAAM,MAAM,yBAAyB,GAAG;IACtC;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,mBAAmB,EAClC,OAAO,CAAC,EAAE,yBAAyB,uBAsIpC"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { TranslationSidebar } from "./sidebar/TranslationSidebar";
|
|
|
7
7
|
import { TranslationManagement } from "./translation-center/TranslationManagement";
|
|
8
8
|
import { RecentTranslations } from "./translation-center/RecentTranslations";
|
|
9
9
|
import { LocalizationSetupStep } from "./setup/LocalizationSetupStep";
|
|
10
|
+
import { TranslationServicesPanel } from "./settings/TranslationServicesPanel";
|
|
10
11
|
import { Languages as LucideLanguages, LayoutGrid as LucideLayoutGrid, Globe as LucideGlobe, } from "lucide-react";
|
|
11
12
|
const LanguagesIcon = LucideLanguages;
|
|
12
13
|
const LayoutGridIcon = LucideLayoutGrid;
|
|
@@ -87,6 +88,7 @@ export { TranslationManagement } from "./translation-center/TranslationManagemen
|
|
|
87
88
|
export { RecentTranslations } from "./translation-center/RecentTranslations";
|
|
88
89
|
export { BatchTranslationView } from "./translation-center/BatchTranslationView";
|
|
89
90
|
export { LocalizationSetupStep } from "./setup/LocalizationSetupStep";
|
|
91
|
+
export { TranslationServicesPanel } from "./settings/TranslationServicesPanel";
|
|
90
92
|
export { defaultTranslateAll, generateBatchId, performDefaultTranslation } from "./LocalizeItemUtils";
|
|
91
93
|
export * from "./steps/types";
|
|
92
94
|
/**
|
|
@@ -173,5 +175,49 @@ export function configureLocalization(configuration, options) {
|
|
|
173
175
|
};
|
|
174
176
|
}
|
|
175
177
|
}
|
|
178
|
+
// Add Localization settings group
|
|
179
|
+
if (!configuration.settings) {
|
|
180
|
+
configuration.settings = { groups: [] };
|
|
181
|
+
}
|
|
182
|
+
// Check if Localization group already exists
|
|
183
|
+
const localizationGroupIndex = configuration.settings.groups.findIndex((group) => group.title === "Localization");
|
|
184
|
+
const translationServicesPanel = {
|
|
185
|
+
id: "translation-services",
|
|
186
|
+
title: "Translation Services",
|
|
187
|
+
subtitle: "Configure translation services (OpenAI, Azure, DeepL, etc.)",
|
|
188
|
+
icon: _jsx(LanguagesIcon, { strokeWidth: 1 }),
|
|
189
|
+
content: _jsx(TranslationServicesPanel, {}),
|
|
190
|
+
};
|
|
191
|
+
if (localizationGroupIndex >= 0) {
|
|
192
|
+
// Group exists, check if panel is already added
|
|
193
|
+
const group = configuration.settings.groups[localizationGroupIndex];
|
|
194
|
+
if (group) {
|
|
195
|
+
const hasPanel = group.panels.some((p) => p.id === "translation-services");
|
|
196
|
+
if (!hasPanel) {
|
|
197
|
+
group.panels.push(translationServicesPanel);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
// Group doesn't exist, create it
|
|
203
|
+
const groups = configuration.settings.groups;
|
|
204
|
+
const aboutIndex = groups.findIndex((g) => g.title === "About");
|
|
205
|
+
if (aboutIndex >= 0) {
|
|
206
|
+
// Insert before About section
|
|
207
|
+
groups.splice(aboutIndex, 0, {
|
|
208
|
+
title: "Localization",
|
|
209
|
+
icon: _jsx(LanguagesIcon, { strokeWidth: 1 }),
|
|
210
|
+
panels: [translationServicesPanel],
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// No About section found, push to end
|
|
215
|
+
groups.push({
|
|
216
|
+
title: "Localization",
|
|
217
|
+
icon: _jsx(LanguagesIcon, { strokeWidth: 1 }),
|
|
218
|
+
panels: [translationServicesPanel],
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
176
222
|
return configuration;
|
|
177
223
|
}
|
|
@@ -24,12 +24,30 @@ export type AvailableTranslationService = {
|
|
|
24
24
|
templateName: string;
|
|
25
25
|
};
|
|
26
26
|
export declare function getAvailableTranslationServices(): Promise<import("@parhelia/core").ExecutionResult<AvailableTranslationService[]>>;
|
|
27
|
-
export declare function createProviderSettings(serviceName: string, templateId: string, language?: string): Promise<import("@parhelia/core").ExecutionResult<{
|
|
27
|
+
export declare function createProviderSettings(serviceName: string, templateId: string, language?: string, structureSettings?: TranslationStructureSettings): Promise<import("@parhelia/core").ExecutionResult<{
|
|
28
28
|
success: boolean;
|
|
29
29
|
itemId: string;
|
|
30
30
|
itemPath: string;
|
|
31
31
|
message: string;
|
|
32
32
|
}>>;
|
|
33
|
+
export type TranslationStructureSettings = {
|
|
34
|
+
translationFolderPath: string;
|
|
35
|
+
translationFolderTemplateId: string;
|
|
36
|
+
translationProvidersPath: string;
|
|
37
|
+
translationProvidersTemplateId: string;
|
|
38
|
+
};
|
|
39
|
+
export type TranslationStructureItemInfo = {
|
|
40
|
+
exists: boolean;
|
|
41
|
+
itemId?: string;
|
|
42
|
+
path?: string;
|
|
43
|
+
templateId?: string;
|
|
44
|
+
};
|
|
45
|
+
export type TranslationStructureResponse = {
|
|
46
|
+
translationFolder: TranslationStructureItemInfo;
|
|
47
|
+
translationProvidersFolder: TranslationStructureItemInfo;
|
|
48
|
+
};
|
|
49
|
+
export declare function getTranslationStructure(settings: TranslationStructureSettings): Promise<import("@parhelia/core").ExecutionResult<TranslationStructureResponse>>;
|
|
50
|
+
export declare function ensureTranslationStructure(settings: TranslationStructureSettings): Promise<import("@parhelia/core").ExecutionResult<TranslationStructureResponse>>;
|
|
33
51
|
export type TranslationJobRecord = {
|
|
34
52
|
itemId: string;
|
|
35
53
|
targetLanguage: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translationService.d.ts","sourceRoot":"","sources":["../../src/services/translationService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,MAAM,MAAM,0BAA0B,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,wBAAsB,kBAAkB,CAAC,EAAC,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAC,EAAE;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,iFAKnQ;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,0EAIxD;AAED,wBAAsB,uBAAuB,iFAE5C;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAsB,+BAA+B,qFAEpD;AAED,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,MAAa;
|
|
1
|
+
{"version":3,"file":"translationService.d.ts","sourceRoot":"","sources":["../../src/services/translationService.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,8 +11,32 @@ export async function getTranslationProviders() {
|
|
|
11
11
|
export async function getAvailableTranslationServices() {
|
|
12
12
|
return await get(`/parhelia/translation/availableServices`);
|
|
13
13
|
}
|
|
14
|
-
export async function createProviderSettings(serviceName, templateId, language = "en") {
|
|
15
|
-
return await post("/parhelia/translation/createProviderSettings", {
|
|
14
|
+
export async function createProviderSettings(serviceName, templateId, language = "en", structureSettings) {
|
|
15
|
+
return await post("/parhelia/translation/createProviderSettings", {
|
|
16
|
+
serviceName,
|
|
17
|
+
templateId,
|
|
18
|
+
language,
|
|
19
|
+
translationFolderPath: structureSettings?.translationFolderPath,
|
|
20
|
+
translationFolderTemplateId: structureSettings?.translationFolderTemplateId,
|
|
21
|
+
translationProvidersPath: structureSettings?.translationProvidersPath,
|
|
22
|
+
translationProvidersTemplateId: structureSettings?.translationProvidersTemplateId,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export async function getTranslationStructure(settings) {
|
|
26
|
+
return await post("/parhelia/translation/getTranslationStructure", {
|
|
27
|
+
translationFolderPath: settings.translationFolderPath,
|
|
28
|
+
translationFolderTemplateId: settings.translationFolderTemplateId,
|
|
29
|
+
translationProvidersPath: settings.translationProvidersPath,
|
|
30
|
+
translationProvidersTemplateId: settings.translationProvidersTemplateId,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export async function ensureTranslationStructure(settings) {
|
|
34
|
+
return await post("/parhelia/translation/ensureTranslationStructure", {
|
|
35
|
+
translationFolderPath: settings.translationFolderPath,
|
|
36
|
+
translationFolderTemplateId: settings.translationFolderTemplateId,
|
|
37
|
+
translationProvidersPath: settings.translationProvidersPath,
|
|
38
|
+
translationProvidersTemplateId: settings.translationProvidersTemplateId,
|
|
39
|
+
});
|
|
16
40
|
}
|
|
17
41
|
export async function listBatchTranslationJobs(batchId) {
|
|
18
42
|
return await get(`/parhelia/translation/batchJobs?batchId=${encodeURIComponent(batchId)}`);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings panel for Translation Services configuration.
|
|
3
|
+
* Configure translation services (OpenAI, Azure, DeepL, etc.) registered in DI.
|
|
4
|
+
*/
|
|
5
|
+
export declare function TranslationServicesPanel(): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export default TranslationServicesPanel;
|
|
7
|
+
//# sourceMappingURL=TranslationServicesPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TranslationServicesPanel.d.ts","sourceRoot":"","sources":["../../src/settings/TranslationServicesPanel.tsx"],"names":[],"mappings":"AAgDA;;;GAGG;AACH,wBAAgB,wBAAwB,4CAggBvC;AAED,eAAe,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useState, useEffect } from "react";
|
|
3
|
+
import { Button, useEditContext, Splitter, ItemConfigPanel } from "@parhelia/core";
|
|
4
|
+
import { CheckCircle as LucideCheckCircle, AlertCircle as LucideAlertCircle, RefreshCw as LucideRefreshCw, Plus as LucidePlus, Settings as LucideSettings, } from "lucide-react";
|
|
5
|
+
import { getAvailableTranslationServices, createProviderSettings, getTranslationStructure, ensureTranslationStructure, } from "../services/translationService";
|
|
6
|
+
const CheckCircleIcon = LucideCheckCircle;
|
|
7
|
+
const AlertCircleIcon = LucideAlertCircle;
|
|
8
|
+
const RefreshCwIcon = LucideRefreshCw;
|
|
9
|
+
const PlusIcon = LucidePlus;
|
|
10
|
+
const SettingsIcon = LucideSettings;
|
|
11
|
+
const DEFAULT_STRUCTURE_SETTINGS = {
|
|
12
|
+
translationFolderPath: "/sitecore/system/Parhelia/Settings/Translation",
|
|
13
|
+
translationFolderTemplateId: "b1e40cfe-6e36-4a0e-a49e-19c10b2127b7",
|
|
14
|
+
translationProvidersPath: "/sitecore/system/Parhelia/Settings/Translation/Translation Providers",
|
|
15
|
+
translationProvidersTemplateId: "1e7ee67d-fab9-47c8-b159-d4002f1a84f9",
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Settings panel for Translation Services configuration.
|
|
19
|
+
* Configure translation services (OpenAI, Azure, DeepL, etc.) registered in DI.
|
|
20
|
+
*/
|
|
21
|
+
export function TranslationServicesPanel() {
|
|
22
|
+
const editContext = useEditContext();
|
|
23
|
+
const [state, setState] = useState("loading");
|
|
24
|
+
const [services, setServices] = useState([]);
|
|
25
|
+
const [error, setError] = useState(null);
|
|
26
|
+
const [selectedConfigTarget, setSelectedConfigTarget] = useState(null);
|
|
27
|
+
const [structureSettings, setStructureSettings] = useState(DEFAULT_STRUCTURE_SETTINGS);
|
|
28
|
+
const [structureState, setStructureState] = useState(null);
|
|
29
|
+
const [structureLoading, setStructureLoading] = useState(false);
|
|
30
|
+
const [ensuringStructure, setEnsuringStructure] = useState(false);
|
|
31
|
+
const handleOpenConfig = useCallback((service) => {
|
|
32
|
+
if (service.isConfigured && service.settingsItemId) {
|
|
33
|
+
setSelectedConfigTarget({
|
|
34
|
+
key: `service:${service.serviceName}`,
|
|
35
|
+
itemId: service.settingsItemId,
|
|
36
|
+
title: `Configure: ${service.displayName || service.serviceName}`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}, []);
|
|
40
|
+
const handleOpenStructureConfig = useCallback((itemId, title) => {
|
|
41
|
+
setSelectedConfigTarget({
|
|
42
|
+
key: `structure:${itemId}`,
|
|
43
|
+
itemId,
|
|
44
|
+
title,
|
|
45
|
+
});
|
|
46
|
+
}, []);
|
|
47
|
+
const handleCloseConfig = useCallback(() => {
|
|
48
|
+
setSelectedConfigTarget(null);
|
|
49
|
+
}, []);
|
|
50
|
+
const loadStructure = useCallback(async () => {
|
|
51
|
+
try {
|
|
52
|
+
setStructureLoading(true);
|
|
53
|
+
const result = await getTranslationStructure(structureSettings);
|
|
54
|
+
if (result.type === "success" && result.data) {
|
|
55
|
+
const success = result.data.success !== false;
|
|
56
|
+
const response = result.data.success !== undefined ? result.data.data : result.data;
|
|
57
|
+
if (success && response) {
|
|
58
|
+
setStructureState(response);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
throw new Error(result.data.error || result.details || "Failed to read translation structure");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
throw new Error(result.details || "Failed to read translation structure");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
setError(e?.message || "Failed to read translation structure");
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
setStructureLoading(false);
|
|
73
|
+
}
|
|
74
|
+
}, [structureSettings]);
|
|
75
|
+
const ensureStructure = useCallback(async () => {
|
|
76
|
+
try {
|
|
77
|
+
setEnsuringStructure(true);
|
|
78
|
+
setError(null);
|
|
79
|
+
const result = await ensureTranslationStructure(structureSettings);
|
|
80
|
+
if (result.type === "success" && result.data) {
|
|
81
|
+
const success = result.data.success !== false;
|
|
82
|
+
const response = result.data.success !== undefined ? result.data.data : result.data;
|
|
83
|
+
if (success && response) {
|
|
84
|
+
setStructureState(response);
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
throw new Error(result.data.error || result.details || "Failed to create translation structure");
|
|
88
|
+
}
|
|
89
|
+
throw new Error(result.details || "Failed to create translation structure");
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
setError(e?.message || "Failed to create translation structure");
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
setEnsuringStructure(false);
|
|
97
|
+
}
|
|
98
|
+
}, [structureSettings]);
|
|
99
|
+
const loadData = useCallback(async () => {
|
|
100
|
+
try {
|
|
101
|
+
setState("loading");
|
|
102
|
+
setError(null);
|
|
103
|
+
await loadStructure();
|
|
104
|
+
const result = await getAvailableTranslationServices();
|
|
105
|
+
if (result.type === "success" && result.data) {
|
|
106
|
+
// Backend returns ApiResponse<T>, so data is wrapped: { success: true, data: [...] }
|
|
107
|
+
const availableServices = Array.isArray(result.data)
|
|
108
|
+
? result.data
|
|
109
|
+
: result.data.data || [];
|
|
110
|
+
const serviceStates = availableServices.map((svc) => ({
|
|
111
|
+
...svc,
|
|
112
|
+
creating: false
|
|
113
|
+
}));
|
|
114
|
+
setServices(serviceStates);
|
|
115
|
+
setState(availableServices.length === 0 ? "error" : "success");
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
setState("error");
|
|
119
|
+
setError(result.details || "Failed to load translation services. The translation API may not be available.");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
setState("error");
|
|
124
|
+
setError(e?.message || "Failed to load translation services");
|
|
125
|
+
}
|
|
126
|
+
}, [loadStructure]);
|
|
127
|
+
const handleStructureInputChange = useCallback((field) => (e) => {
|
|
128
|
+
setStructureSettings(prev => ({
|
|
129
|
+
...prev,
|
|
130
|
+
[field]: e.target.value,
|
|
131
|
+
}));
|
|
132
|
+
}, []);
|
|
133
|
+
const createSettings = useCallback(async (serviceName, templateId) => {
|
|
134
|
+
try {
|
|
135
|
+
setServices(prev => prev.map(s => s.serviceName === serviceName ? { ...s, creating: true } : s));
|
|
136
|
+
setError(null);
|
|
137
|
+
const language = editContext?.item?.language ??
|
|
138
|
+
editContext?.currentItemDescriptor?.language ??
|
|
139
|
+
"en";
|
|
140
|
+
const result = await createProviderSettings(serviceName, templateId, language, structureSettings);
|
|
141
|
+
if (result.type === "success" && result.data) {
|
|
142
|
+
// Backend returns ApiResponse<T>, so unwrap: { success: true, data: { itemId, itemPath } }
|
|
143
|
+
const response = result.data.success ? result.data.data : result.data;
|
|
144
|
+
const success = result.data.success !== false;
|
|
145
|
+
if (success && response) {
|
|
146
|
+
setServices(prev => prev.map(s => s.serviceName === serviceName
|
|
147
|
+
? { ...s, isConfigured: true, creating: false, settingsItemId: response.itemId }
|
|
148
|
+
: s));
|
|
149
|
+
// Reload data to ensure consistency
|
|
150
|
+
setTimeout(() => loadData(), 500);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
throw new Error(result.data.error || result.details || "Failed to create settings");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
throw new Error(result.details || "Failed to create settings");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (e) {
|
|
161
|
+
const errorMessage = e?.message || "Unknown error";
|
|
162
|
+
// Provide more helpful error messages for common issues
|
|
163
|
+
let displayMessage = errorMessage;
|
|
164
|
+
if (errorMessage.includes("Translation Providers folder not found") ||
|
|
165
|
+
errorMessage.includes("Translation folder not found")) {
|
|
166
|
+
displayMessage = "The required folder structure is missing. Configure and create the parent items in the Settings section above.";
|
|
167
|
+
}
|
|
168
|
+
else if (errorMessage.includes("already exists")) {
|
|
169
|
+
displayMessage = `Settings for ${serviceName} already exist. Please refresh the list.`;
|
|
170
|
+
// Reload data to show updated status
|
|
171
|
+
setTimeout(() => loadData(), 500);
|
|
172
|
+
}
|
|
173
|
+
setError(`Failed to create settings for ${serviceName}: ${displayMessage}`);
|
|
174
|
+
setServices(prev => prev.map(s => s.serviceName === serviceName ? { ...s, creating: false } : s));
|
|
175
|
+
}
|
|
176
|
+
}, [editContext, loadData, structureSettings]);
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
loadData();
|
|
179
|
+
}, [loadData]);
|
|
180
|
+
const statusIcon = (currentState) => {
|
|
181
|
+
if (currentState === "success")
|
|
182
|
+
return _jsx(CheckCircleIcon, { className: "h-4 w-4 text-green-600", strokeWidth: 1 });
|
|
183
|
+
if (currentState === "error")
|
|
184
|
+
return _jsx(AlertCircleIcon, { className: "h-4 w-4 text-red-600", strokeWidth: 1 });
|
|
185
|
+
return (_jsx(RefreshCwIcon, { className: "h-4 w-4 animate-spin text-amber-600", strokeWidth: 1 }));
|
|
186
|
+
};
|
|
187
|
+
const configuredCount = services.filter(s => s.isConfigured).length;
|
|
188
|
+
const totalCount = services.length;
|
|
189
|
+
const translationFolderExists = !!structureState?.translationFolder?.exists;
|
|
190
|
+
const providersFolderExists = !!structureState?.translationProvidersFolder?.exists;
|
|
191
|
+
// Build the services list content
|
|
192
|
+
const servicesListContent = (_jsx("div", { className: "h-full overflow-auto p-4", children: _jsx("div", { className: "mx-auto", children: _jsx("div", { className: "rounded-lg bg-white p-4 md:p-6", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-semibold text-gray-900", children: "Prerequisites" }), _jsxs("div", { className: "mt-1 flex items-center gap-2", children: [translationFolderExists && providersFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 text-green-600", strokeWidth: 1 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 text-amber-500", strokeWidth: 1 })), _jsx("span", { className: "text-sm text-gray-700", children: translationFolderExists && providersFolderExists
|
|
193
|
+
? "All parent items found"
|
|
194
|
+
: "Parent items missing" })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { size: "sm", variant: "outline", onClick: loadStructure, disabled: structureLoading || ensuringStructure, children: [_jsx(RefreshCwIcon, { strokeWidth: 1, className: `h-4 w-4 ${structureLoading ? "animate-spin" : ""}` }), "Refresh"] }), !providersFolderExists && (_jsxs(Button, { size: "sm", onClick: ensureStructure, disabled: ensuringStructure || structureLoading, children: [ensuringStructure ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-4 w-4 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1.5, className: "h-4 w-4" })), "Ensure Items"] }))] })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: `flex items-center justify-between rounded border p-3 text-sm transition-shadow hover:shadow-sm ${selectedConfigTarget?.key === `structure:${structureState?.translationFolder?.itemId}`
|
|
195
|
+
? "border-blue-400 bg-blue-50"
|
|
196
|
+
: "border-gray-200 bg-white"}`, children: [_jsxs("div", { className: "flex items-center gap-3 flex-1", children: [translationFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 text-green-600 flex-shrink-0", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 text-amber-500 flex-shrink-0", strokeWidth: 1.5 })), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "font-medium text-gray-900", children: "Translation folder" }), _jsx("div", { className: "text-xs text-gray-500 truncate", children: structureSettings.translationFolderPath })] })] }), _jsx("div", { className: "flex items-center gap-2 ml-4", children: translationFolderExists && structureState?.translationFolder?.itemId && (_jsxs(Button, { size: "sm", variant: selectedConfigTarget?.key === `structure:${structureState.translationFolder.itemId}`
|
|
197
|
+
? "default"
|
|
198
|
+
: "ghost", onClick: () => handleOpenStructureConfig(structureState.translationFolder.itemId, "Configure: Translation folder"), className: "shrink-0", children: [_jsx(SettingsIcon, { className: "h-4 w-4", strokeWidth: 1.5 }), "Configure"] })) })] }), _jsxs("div", { className: `flex items-center justify-between rounded border p-3 text-sm transition-shadow hover:shadow-sm ${selectedConfigTarget?.key === `structure:${structureState?.translationProvidersFolder?.itemId}`
|
|
199
|
+
? "border-blue-400 bg-blue-50"
|
|
200
|
+
: "border-gray-200 bg-white"}`, children: [_jsxs("div", { className: "flex items-center gap-3 flex-1", children: [providersFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 text-green-600 flex-shrink-0", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 text-amber-500 flex-shrink-0", strokeWidth: 1.5 })), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "font-medium text-gray-900", children: "Translation providers folder" }), _jsx("div", { className: "text-xs text-gray-500 truncate", children: structureSettings.translationProvidersPath })] })] }), _jsx("div", { className: "flex items-center gap-2 ml-4", children: providersFolderExists && structureState?.translationProvidersFolder?.itemId && (_jsxs(Button, { size: "sm", variant: selectedConfigTarget?.key === `structure:${structureState.translationProvidersFolder.itemId}`
|
|
201
|
+
? "default"
|
|
202
|
+
: "ghost", onClick: () => handleOpenStructureConfig(structureState.translationProvidersFolder.itemId, "Configure: Translation Providers folder"), className: "shrink-0", children: [_jsx(SettingsIcon, { className: "h-4 w-4", strokeWidth: 1.5 }), "Configure"] })) })] })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-semibold text-gray-900", children: "Providers" }), _jsxs("div", { className: "mt-1 flex items-center gap-2", children: [statusIcon(state), _jsx("span", { className: "text-sm text-gray-700", children: totalCount > 0
|
|
203
|
+
? `${configuredCount} of ${totalCount} service${totalCount !== 1 ? "s" : ""} configured`
|
|
204
|
+
: "No services found" })] })] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: loadData, children: [_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-4 w-4" }), "Refresh"] })] }), totalCount === 0 && state === "success" && (_jsx("div", { className: "rounded border border-yellow-200 bg-yellow-50 p-3 text-sm text-yellow-800", children: "No translation services are registered in dependency injection. Please check the server configuration." })), services.length > 0 && (_jsx("div", { className: "space-y-1", children: services.map((service) => {
|
|
205
|
+
const isSelected = selectedConfigTarget?.key === `service:${service.serviceName}`;
|
|
206
|
+
return (_jsxs("div", { className: `flex items-center justify-between rounded border p-3 text-sm transition-shadow hover:shadow-sm ${isSelected
|
|
207
|
+
? "border-blue-400 bg-blue-50"
|
|
208
|
+
: "border-gray-200 bg-white"}`, children: [_jsxs("div", { className: "flex items-center gap-3 flex-1", children: [service.isConfigured ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 text-green-600 flex-shrink-0", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 text-amber-500 flex-shrink-0", strokeWidth: 1.5 })), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "font-medium text-gray-900", children: service.displayName || service.serviceName }), service.displayName && service.displayName !== service.serviceName && (_jsxs("div", { className: "text-xs text-gray-500", children: ["Service: ", service.serviceName] })), service.isConfigured && service.supportedLanguages && service.supportedLanguages.length > 0 && (_jsxs("div", { className: "text-xs text-gray-500 mt-1", children: ["Languages: ", service.supportedLanguages.join(", ")] })), !service.isConfigured && (_jsx("div", { className: "text-xs text-amber-600 mt-1", children: "Not configured" }))] })] }), _jsx("div", { className: "flex items-center gap-2 ml-4", children: service.isConfigured && service.settingsItemId ? (_jsxs(Button, { size: "sm", variant: isSelected ? "default" : "ghost", onClick: () => handleOpenConfig(service), className: "shrink-0", children: [_jsx(SettingsIcon, { className: "h-4 w-4", strokeWidth: 1.5 }), "Configure"] })) : (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => createSettings(service.serviceName, service.templateId), disabled: service.creating, title: `Create settings using template: ${service.templateName}`, className: "shrink-0", children: [service.creating ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-4 w-4 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1.5, className: "h-4 w-4" })), "Create Settings"] })) })] }, service.serviceName));
|
|
209
|
+
}) })), error && (_jsx("div", { className: "rounded border border-red-200 bg-red-50 p-3 text-sm text-red-700 whitespace-pre-wrap", children: error }))] }) }) }) }));
|
|
210
|
+
// Build splitter panels - only show config panel when a service is selected
|
|
211
|
+
const panels = selectedConfigTarget?.itemId
|
|
212
|
+
? [
|
|
213
|
+
{
|
|
214
|
+
name: "services-list",
|
|
215
|
+
defaultSize: "auto",
|
|
216
|
+
content: servicesListContent,
|
|
217
|
+
className: "overflow-hidden",
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: "service-config",
|
|
221
|
+
defaultSize: 400,
|
|
222
|
+
content: (_jsx(ItemConfigPanel, { itemId: selectedConfigTarget.itemId, title: selectedConfigTarget.title, onClose: handleCloseConfig }, selectedConfigTarget.itemId)),
|
|
223
|
+
className: "overflow-hidden",
|
|
224
|
+
},
|
|
225
|
+
]
|
|
226
|
+
: [
|
|
227
|
+
{
|
|
228
|
+
name: "services-list",
|
|
229
|
+
defaultSize: "auto",
|
|
230
|
+
content: servicesListContent,
|
|
231
|
+
className: "overflow-hidden",
|
|
232
|
+
},
|
|
233
|
+
];
|
|
234
|
+
const SplitterComponent = Splitter;
|
|
235
|
+
return (_jsx(SplitterComponent, { panels: panels, localStorageKey: "translation-services-panel-splitter", direction: "horizontal", className: "h-full" }));
|
|
236
|
+
}
|
|
237
|
+
export default TranslationServicesPanel;
|