@parhelia/localization 0.1.11200 → 0.1.11455
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/README.md +33 -33
- package/dist/LocalizeItemCommand.js +4 -4
- package/dist/LocalizeItemDialog.js +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -36
- package/dist/setup/LocalizationSetupStep.js +6 -6
- package/dist/sidebar/TranslationSidebar.d.ts.map +1 -1
- package/dist/sidebar/TranslationSidebar.js +36 -18
- package/dist/steps/MetadataInputStep.d.ts.map +1 -1
- package/dist/steps/MetadataInputStep.js +1 -1
- package/dist/steps/PromptCustomizationStep.js +2 -2
- package/dist/steps/ServiceLanguageSelectionStep.js +4 -4
- package/dist/steps/SubitemDiscoveryStep.js +7 -7
- package/dist/translation-center/BatchTranslationView.d.ts.map +1 -1
- package/dist/translation-center/BatchTranslationView.js +19 -18
- package/dist/translation-center/RecentTranslations.d.ts.map +1 -1
- package/dist/translation-center/RecentTranslations.js +40 -8
- package/dist/translation-center/TranslationManagement.d.ts.map +1 -1
- package/dist/translation-center/TranslationManagement.js +3 -3
- package/package.json +1 -1
- package/dist/dist/LocalizeItemCommand.d.ts +0 -8
- package/dist/dist/LocalizeItemCommand.d.ts.map +0 -1
- package/dist/dist/LocalizeItemCommand.js +0 -48
- package/dist/dist/LocalizeItemDialog.d.ts +0 -4
- package/dist/dist/LocalizeItemDialog.d.ts.map +0 -1
- package/dist/dist/LocalizeItemDialog.js +0 -129
- package/dist/dist/LocalizeItemUtils.d.ts +0 -17
- package/dist/dist/LocalizeItemUtils.d.ts.map +0 -1
- package/dist/dist/LocalizeItemUtils.js +0 -93
- package/dist/dist/api/discovery.d.ts +0 -36
- package/dist/dist/api/discovery.d.ts.map +0 -1
- package/dist/dist/api/discovery.js +0 -29
- package/dist/dist/constants.d.ts +0 -15
- package/dist/dist/constants.d.ts.map +0 -1
- package/dist/dist/constants.js +0 -21
- package/dist/dist/hooks/useTranslationWizard.d.ts +0 -6
- package/dist/dist/hooks/useTranslationWizard.d.ts.map +0 -1
- package/dist/dist/hooks/useTranslationWizard.js +0 -78
- package/dist/dist/index.d.ts +0 -69
- package/dist/dist/index.d.ts.map +0 -1
- package/dist/dist/index.js +0 -152
- package/dist/dist/services/translationService.d.ts +0 -102
- package/dist/dist/services/translationService.d.ts.map +0 -1
- package/dist/dist/services/translationService.js +0 -37
- package/dist/dist/setup/LocalizationSetupStep.d.ts +0 -3
- package/dist/dist/setup/LocalizationSetupStep.d.ts.map +0 -1
- package/dist/dist/setup/LocalizationSetupStep.js +0 -115
- package/dist/dist/sidebar/TranslationSidebar.d.ts +0 -2
- package/dist/dist/sidebar/TranslationSidebar.d.ts.map +0 -1
- package/dist/dist/sidebar/TranslationSidebar.js +0 -95
- package/dist/dist/steps/MetadataInputStep.d.ts +0 -4
- package/dist/dist/steps/MetadataInputStep.d.ts.map +0 -1
- package/dist/dist/steps/MetadataInputStep.js +0 -38
- package/dist/dist/steps/ServiceLanguageSelectionStep.d.ts +0 -3
- package/dist/dist/steps/ServiceLanguageSelectionStep.d.ts.map +0 -1
- package/dist/dist/steps/ServiceLanguageSelectionStep.js +0 -120
- package/dist/dist/steps/SubitemDiscoveryStep.d.ts +0 -3
- package/dist/dist/steps/SubitemDiscoveryStep.d.ts.map +0 -1
- package/dist/dist/steps/SubitemDiscoveryStep.js +0 -415
- package/dist/dist/steps/index.d.ts +0 -5
- package/dist/dist/steps/index.d.ts.map +0 -1
- package/dist/dist/steps/index.js +0 -4
- package/dist/dist/steps/types.d.ts +0 -68
- package/dist/dist/steps/types.d.ts.map +0 -1
- package/dist/dist/steps/types.js +0 -1
- package/dist/dist/translation-center/BatchTranslationView.d.ts +0 -7
- package/dist/dist/translation-center/BatchTranslationView.d.ts.map +0 -1
- package/dist/dist/translation-center/BatchTranslationView.js +0 -507
- package/dist/dist/translation-center/RecentTranslations.d.ts +0 -2
- package/dist/dist/translation-center/RecentTranslations.d.ts.map +0 -1
- package/dist/dist/translation-center/RecentTranslations.js +0 -195
- package/dist/dist/translation-center/TranslationManagement.d.ts +0 -2
- package/dist/dist/translation-center/TranslationManagement.d.ts.map +0 -1
- package/dist/dist/translation-center/TranslationManagement.js +0 -25
- package/dist/dist/types.d.ts +0 -18
- package/dist/dist/types.d.ts.map +0 -1
- package/dist/dist/types.js +0 -1
- package/dist/dist/utils/createVersions.d.ts +0 -14
- package/dist/dist/utils/createVersions.d.ts.map +0 -1
- package/dist/dist/utils/createVersions.js +0 -26
package/README.md
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
# @parhelia/localization
|
|
2
|
-
|
|
3
|
-
Localization and translation features for Parhelia visual editor.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @parhelia/localization
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Usage
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
import { LocalizeItemDialog, TranslationSidebar } from '@parhelia/localization';
|
|
15
|
-
import '@parhelia/localization/styles.css';
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Features
|
|
19
|
-
|
|
20
|
-
- Translation wizard
|
|
21
|
-
- Localization setup
|
|
22
|
-
- Translation center
|
|
23
|
-
- Multi-language content management
|
|
24
|
-
- Version creation for localized content
|
|
25
|
-
|
|
26
|
-
## License
|
|
27
|
-
|
|
28
|
-
See LICENSE file for details.
|
|
29
|
-
|
|
30
|
-
## Documentation
|
|
31
|
-
|
|
32
|
-
For complete documentation, visit [https://parhelia.ai](https://parhelia.ai)
|
|
33
|
-
|
|
1
|
+
# @parhelia/localization
|
|
2
|
+
|
|
3
|
+
Localization and translation features for Parhelia visual editor.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @parhelia/localization
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { LocalizeItemDialog, TranslationSidebar } from '@parhelia/localization';
|
|
15
|
+
import '@parhelia/localization/styles.css';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- Translation wizard
|
|
21
|
+
- Localization setup
|
|
22
|
+
- Translation center
|
|
23
|
+
- Multi-language content management
|
|
24
|
+
- Version creation for localized content
|
|
25
|
+
|
|
26
|
+
## License
|
|
27
|
+
|
|
28
|
+
See LICENSE file for details.
|
|
29
|
+
|
|
30
|
+
## Documentation
|
|
31
|
+
|
|
32
|
+
For complete documentation, visit [https://parhelia.ai](https://parhelia.ai)
|
|
33
|
+
|
|
@@ -33,14 +33,14 @@ export const localizeItemCommand = {
|
|
|
33
33
|
if (result?.batchId) {
|
|
34
34
|
const translationManagementEnabled = context.editContext?.configuration?.localization?.translationManagement !== false;
|
|
35
35
|
if (translationManagementEnabled) {
|
|
36
|
-
// Synchronous URL update to avoid race with
|
|
36
|
+
// Synchronous URL update to avoid race with workspace URL sync
|
|
37
37
|
const params = new URLSearchParams(window.location.search);
|
|
38
|
-
params.set("
|
|
38
|
+
params.set("workspace", "translation-management");
|
|
39
39
|
params.set("batchId", result.batchId);
|
|
40
40
|
const newUrl = `${window.location.pathname}?${params.toString()}`;
|
|
41
41
|
window.history.pushState(null, "", newUrl);
|
|
42
|
-
// Now switch the
|
|
43
|
-
context.editContext.
|
|
42
|
+
// Now switch the workspace; URL already contains batchId
|
|
43
|
+
context.editContext.switchWorkspace("translation-management");
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
return result;
|
|
@@ -7,7 +7,7 @@ import { performDefaultTranslation, generateBatchId } from "./LocalizeItemUtils"
|
|
|
7
7
|
const ChevronRightIcon = LucideChevronRight;
|
|
8
8
|
// Note: DialogButtons is an internal component that might need to be added to core exports
|
|
9
9
|
// For now, we'll implement it inline
|
|
10
|
-
const DialogButtons = ({ children, ...props }) => (_jsx("div", { className: "flex justify-end gap-2 pt-4 border-t mt-auto px-6 pb-6", ...props, children: children }));
|
|
10
|
+
const DialogButtons = ({ children, ...props }) => (_jsx("div", { className: "flex justify-end gap-2 pt-4 border-t border-[var(--color-gray-3)] mt-auto px-6 pb-6 bg-background", ...props, children: children }));
|
|
11
11
|
export function LocalizeItemDialog(props) {
|
|
12
12
|
const editContext = props.editContext;
|
|
13
13
|
const configuration = editContext.configuration.translationWizard;
|
|
@@ -184,13 +184,13 @@ export function LocalizeItemDialog(props) {
|
|
|
184
184
|
width: 'min(90vw, 1280px)',
|
|
185
185
|
height: 'min(85vh, 900px)',
|
|
186
186
|
minHeight: '700px'
|
|
187
|
-
}, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { "data-testid": "translation-wizard-title", children: "Translation Wizard" }), _jsx("div", { id: "translation-wizard-description", className: "sr-only", children: currentStep?.description || "Configure and start translation for your content." })] }), _jsxs("div", { className: "flex flex-1 flex-col min-h-0", children: [_jsx("div", { className: "border-b border-gray-
|
|
188
|
-
"border-
|
|
189
|
-
"bg-
|
|
190
|
-
? "text-
|
|
187
|
+
}, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { "data-testid": "translation-wizard-title", children: "Translation Wizard" }), _jsx("div", { id: "translation-wizard-description", className: "sr-only", children: currentStep?.description || "Configure and start translation for your content." })] }), _jsxs("div", { className: "flex flex-1 flex-col min-h-0", children: [_jsx("div", { className: "border-b border-[var(--color-gray-3)] bg-background px-6", "data-testid": "translation-wizard-step-navigation", children: _jsx("div", { className: "flex items-center gap-3 py-3", children: activeSteps.map((step, index) => (_jsxs("div", { className: "flex items-center gap-2", "data-testid": `step-indicator-${step.id}`, children: [_jsx("div", { className: cn("flex h-8 w-8 items-center justify-center rounded-full border text-sm font-medium transition-colors", currentStepIndex === index &&
|
|
188
|
+
"border-[#9650fb] text-[#9650fb] bg-[#f6eeff]", currentStepIndex < index && "border-[var(--color-gray-3)] text-[var(--color-gray-2)]", currentStepIndex > index &&
|
|
189
|
+
"bg-[#9650fb] text-white border-[#9650fb]"), "data-testid": `step-indicator-circle-${step.id}`, children: currentStepIndex > index ? "✓" : index + 1 }), _jsx("span", { className: cn("text-sm", currentStepIndex === index
|
|
190
|
+
? "text-[#9650fb] font-medium"
|
|
191
191
|
: currentStepIndex > index
|
|
192
|
-
? "text-
|
|
193
|
-
: "text-gray-
|
|
192
|
+
? "text-[#9650fb]"
|
|
193
|
+
: "text-[var(--color-gray-2)]"), "data-testid": `step-indicator-label-${step.id}`, children: step.name }), index < activeSteps.length - 1 && (_jsx(ChevronRightIcon, { className: "w-4 h-4 text-[var(--color-gray-3)] mx-2", strokeWidth: 1 }))] }, step.id))) }) }), _jsx("div", { className: "flex-1 overflow-y-auto min-h-0 bg-[var(--color-gray-5)]", "data-testid": "translation-wizard-step-content", children: _jsx("div", { className: "h-full relative", children: activeSteps.map((step, index) => {
|
|
194
194
|
const StepComponent = step.component;
|
|
195
195
|
const isActive = index === currentStepIndex;
|
|
196
196
|
if (!StepComponent)
|
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;AAYtD,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,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,uBAqFpC"}
|
package/dist/index.js
CHANGED
|
@@ -7,10 +7,10 @@ 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 { Languages as LucideLanguages, LayoutGrid as LucideLayoutGrid, } from "lucide-react";
|
|
11
|
-
import { pageEditorViewBase } from "@parhelia/core";
|
|
10
|
+
import { Languages as LucideLanguages, LayoutGrid as LucideLayoutGrid, Globe as LucideGlobe, } from "lucide-react";
|
|
12
11
|
const LanguagesIcon = LucideLanguages;
|
|
13
12
|
const LayoutGridIcon = LucideLayoutGrid;
|
|
13
|
+
const GlobeIcon = LucideGlobe;
|
|
14
14
|
const DEFAULT_TRANSLATION_WIZARD_CONFIGURATION = {
|
|
15
15
|
steps: [
|
|
16
16
|
{
|
|
@@ -50,6 +50,36 @@ const SINGLE_ITEM_TRANSLATION_WIZARD_CONFIGURATION = {
|
|
|
50
50
|
// No SubitemDiscoveryStep - single item translation only
|
|
51
51
|
],
|
|
52
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* Translation sidebar definition for the Editor workspace
|
|
55
|
+
*/
|
|
56
|
+
const translateSidebar = {
|
|
57
|
+
id: "translate",
|
|
58
|
+
title: "Languages & Versions",
|
|
59
|
+
icon: _jsx(LanguagesIcon, { strokeWidth: 1 }),
|
|
60
|
+
position: "left",
|
|
61
|
+
sortOrder: 55, // After workbox (50), before dictionary (60)
|
|
62
|
+
panels: [
|
|
63
|
+
{
|
|
64
|
+
name: "translation",
|
|
65
|
+
title: "Languages & Versions",
|
|
66
|
+
content: _jsx(TranslationSidebar, {}),
|
|
67
|
+
initialSize: 100,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Translation Management workspace definition
|
|
73
|
+
*/
|
|
74
|
+
const translationManagementWorkspace = {
|
|
75
|
+
id: "translation-management",
|
|
76
|
+
title: "Translation Management",
|
|
77
|
+
icon: _jsx(GlobeIcon, { strokeWidth: 1 }),
|
|
78
|
+
component: _jsx(TranslationManagement, {}),
|
|
79
|
+
menuBar: _jsx(_Fragment, {}),
|
|
80
|
+
supportsSidebars: false,
|
|
81
|
+
sortOrder: 30,
|
|
82
|
+
};
|
|
53
83
|
export { DEFAULT_TRANSLATION_WIZARD_CONFIGURATION, SINGLE_ITEM_TRANSLATION_WIZARD_CONFIGURATION };
|
|
54
84
|
export { LocalizeItemDialog } from "./LocalizeItemDialog";
|
|
55
85
|
export { localizeItemCommand } from "./LocalizeItemCommand";
|
|
@@ -77,6 +107,7 @@ export * from "./steps/types";
|
|
|
77
107
|
*/
|
|
78
108
|
export function configureLocalization(configuration, options) {
|
|
79
109
|
const enableMultiItem = options?.multiItem !== false; // Default to true
|
|
110
|
+
const enableTranslationManagement = options?.translationManagement !== false; // Default to true
|
|
80
111
|
// Add localization setup step
|
|
81
112
|
if (!configuration.setup) {
|
|
82
113
|
configuration.setup = { steps: [] };
|
|
@@ -97,7 +128,7 @@ export function configureLocalization(configuration, options) {
|
|
|
97
128
|
configuration.localization = {};
|
|
98
129
|
}
|
|
99
130
|
configuration.localization.multiItem = enableMultiItem;
|
|
100
|
-
configuration.localization.translationManagement =
|
|
131
|
+
configuration.localization.translationManagement = enableTranslationManagement;
|
|
101
132
|
if (!configuration.commands.allItemCommands) {
|
|
102
133
|
configuration.commands.allItemCommands = [];
|
|
103
134
|
}
|
|
@@ -106,30 +137,17 @@ export function configureLocalization(configuration, options) {
|
|
|
106
137
|
if (!hasLocalizeCommand) {
|
|
107
138
|
configuration.commands.allItemCommands.push(localizeItemCommand);
|
|
108
139
|
}
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
leftSidebar: {
|
|
118
|
-
panels: [
|
|
119
|
-
{
|
|
120
|
-
name: "translation",
|
|
121
|
-
title: "Languages & Versions",
|
|
122
|
-
content: _jsx(TranslationSidebar, {}),
|
|
123
|
-
initialSize: 20,
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
|
-
},
|
|
127
|
-
...pageEditorViewBase,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
140
|
+
// Register translate sidebar in the Editor workspace
|
|
141
|
+
const sidebars = configuration.editor?.sidebars || [];
|
|
142
|
+
const hasTranslateSidebar = sidebars.some((s) => s.id === "translate");
|
|
143
|
+
if (!hasTranslateSidebar) {
|
|
144
|
+
configuration.editor = {
|
|
145
|
+
...configuration.editor,
|
|
146
|
+
sidebars: [...sidebars, translateSidebar],
|
|
147
|
+
};
|
|
130
148
|
}
|
|
131
|
-
// Add Translation Management
|
|
132
|
-
if (
|
|
149
|
+
// Add Translation Management workspace if enabled
|
|
150
|
+
if (enableTranslationManagement) {
|
|
133
151
|
// Create Translation Center configuration
|
|
134
152
|
configuration.translationCenter = {
|
|
135
153
|
groups: [
|
|
@@ -145,16 +163,14 @@ export function configureLocalization(configuration, options) {
|
|
|
145
163
|
},
|
|
146
164
|
],
|
|
147
165
|
};
|
|
148
|
-
//
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
menuBar: _jsx(_Fragment, {}),
|
|
157
|
-
});
|
|
166
|
+
// Register workspace
|
|
167
|
+
const workspaces = configuration.editor?.workspaces || [];
|
|
168
|
+
const hasManagementWorkspace = workspaces.some((w) => w.id === "translation-management");
|
|
169
|
+
if (!hasManagementWorkspace) {
|
|
170
|
+
configuration.editor = {
|
|
171
|
+
...configuration.editor,
|
|
172
|
+
workspaces: [...workspaces, translationManagementWorkspace],
|
|
173
|
+
};
|
|
158
174
|
}
|
|
159
175
|
}
|
|
160
176
|
return configuration;
|
|
@@ -15,12 +15,12 @@ export function LocalizationSetupStep() {
|
|
|
15
15
|
const [services, setServices] = useState([]);
|
|
16
16
|
const statusIcon = useCallback((state) => {
|
|
17
17
|
if (state === "success")
|
|
18
|
-
return _jsx(CheckCircleIcon, { className: "h-4 w-4 text-
|
|
18
|
+
return _jsx(CheckCircleIcon, { className: "h-4 w-4 text-[#8ae048]", strokeWidth: 1 });
|
|
19
19
|
if (state === "error")
|
|
20
|
-
return _jsx(AlertCircleIcon, { className: "h-4 w-4 text-
|
|
20
|
+
return _jsx(AlertCircleIcon, { className: "h-4 w-4 text-destructive", strokeWidth: 1 });
|
|
21
21
|
if (state === "partial")
|
|
22
|
-
return _jsx(AlertCircleIcon, { className: "h-4 w-4 text-
|
|
23
|
-
return (_jsx(RefreshCwIcon, { className: "h-4 w-4 animate-spin text-
|
|
22
|
+
return _jsx(AlertCircleIcon, { className: "h-4 w-4 text-[#ffc310]", strokeWidth: 1 });
|
|
23
|
+
return (_jsx(RefreshCwIcon, { className: "h-4 w-4 animate-spin text-[#9650fb]", strokeWidth: 1 }));
|
|
24
24
|
}, []);
|
|
25
25
|
const checkLocalization = useCallback(async () => {
|
|
26
26
|
try {
|
|
@@ -100,7 +100,7 @@ export function LocalizationSetupStep() {
|
|
|
100
100
|
}, [checkLocalization]);
|
|
101
101
|
const configuredCount = services.filter(s => s.isConfigured).length;
|
|
102
102
|
const totalCount = services.length;
|
|
103
|
-
return (_jsx(Card, { icon: _jsx(LanguagesIcon, { strokeWidth: 1, className: "h-5 w-5" }), title: "Localization setup", description: "Verifies that translation services registered in DI have corresponding Sitecore Settings items.", children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [statusIcon(state), _jsx("span", { className: "text-sm text-gray-
|
|
103
|
+
return (_jsx(Card, { icon: _jsx(LanguagesIcon, { strokeWidth: 1, className: "h-5 w-5" }), title: "Localization setup", description: "Verifies that translation services registered in DI have corresponding Sitecore Settings items.", children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [statusIcon(state), _jsx("span", { className: "text-sm text-[var(--color-gray-1)]", children: state === "success"
|
|
104
104
|
? `All ${totalCount} translation service${totalCount !== 1 ? 's' : ''} configured`
|
|
105
105
|
: state === "partial"
|
|
106
106
|
? `${configuredCount} of ${totalCount} services configured`
|
|
@@ -108,6 +108,6 @@ export function LocalizationSetupStep() {
|
|
|
108
108
|
? `${totalCount} service${totalCount !== 1 ? 's' : ''} found, none configured`
|
|
109
109
|
: state === "error"
|
|
110
110
|
? "No services found"
|
|
111
|
-
: "Checking..." })] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: checkLocalization, children: [_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-4 w-4" }), "Recheck"] })] }), services.length > 0 && (_jsxs("div", { className: "space-y-2 rounded border border-gray-
|
|
111
|
+
: "Checking..." })] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: checkLocalization, children: [_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-4 w-4" }), "Recheck"] })] }), services.length > 0 && (_jsxs("div", { className: "space-y-2 rounded-lg border border-[var(--color-gray-3)] bg-[var(--color-gray-5)] p-3", children: [_jsx("div", { className: "text-xs font-semibold text-[var(--color-gray-2)] uppercase tracking-wide", children: "Translation Services" }), services.map((service) => (_jsxs("div", { className: "flex items-center justify-between rounded-md bg-background p-3 shadow-sm border border-[var(--color-gray-3)]", children: [_jsxs("div", { className: "flex items-center gap-2", children: [service.isConfigured ? (_jsx(CheckCircleIcon, { className: "h-3.5 w-3.5 text-[#8ae048]", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-3.5 w-3.5 text-[#ffc310]", strokeWidth: 1.5 })), _jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-[var(--color-dark)]", children: service.displayName || service.serviceName }), service.displayName && service.displayName !== service.serviceName && (_jsxs("div", { className: "text-xs text-[var(--color-gray-2)]", children: ["Service: ", service.serviceName] })), service.isConfigured && service.supportedLanguages && service.supportedLanguages.length > 0 && (_jsxs("div", { className: "text-xs text-[var(--color-gray-2)]", children: ["Languages: ", service.supportedLanguages.join(", ")] }))] })] }), !service.isConfigured && (_jsxs(Button, { size: "xs", onClick: () => createSettings(service.serviceName, service.templateId), disabled: service.creating, title: `Create using template: ${service.templateName}`, children: [service.creating ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-3 w-3 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1.5, className: "h-3 w-3" })), "Create Settings"] }))] }, service.serviceName)))] })), error && (_jsx("div", { className: "rounded-md border border-[#ffc310]/30 bg-[#ffc310]/10 p-3 text-xs whitespace-pre-wrap text-[var(--color-dark)]", children: error }))] }) }));
|
|
112
112
|
}
|
|
113
113
|
export default LocalizationSetupStep;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TranslationSidebar.d.ts","sourceRoot":"","sources":["../../src/sidebar/TranslationSidebar.tsx"],"names":[],"mappings":"AAcA,wBAAgB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"TranslationSidebar.d.ts","sourceRoot":"","sources":["../../src/sidebar/TranslationSidebar.tsx"],"names":[],"mappings":"AAcA,wBAAgB,kBAAkB,mDA+MjC"}
|
|
@@ -25,7 +25,7 @@ export function TranslationSidebar() {
|
|
|
25
25
|
});
|
|
26
26
|
};
|
|
27
27
|
const languageName = (language) => {
|
|
28
|
-
return (_jsxs("div", { className: "flex items-center gap-2
|
|
28
|
+
return (_jsxs("div", { className: "flex items-center gap-2 text-[var(--color-dark)]", children: [_jsx("img", { src: language.icon, className: "h-5 rounded-sm", alt: language.languageCode }), _jsx("span", { className: "font-medium", children: language.name })] }, language.languageCode));
|
|
29
29
|
};
|
|
30
30
|
const loadTranslationStatus = async () => {
|
|
31
31
|
if (!item)
|
|
@@ -44,6 +44,14 @@ export function TranslationSidebar() {
|
|
|
44
44
|
message.type === "translation-error") {
|
|
45
45
|
if (message.payload.itemId === item?.descriptor.id) {
|
|
46
46
|
loadTranslationStatus();
|
|
47
|
+
// Clear progress when finished or error
|
|
48
|
+
if (message.type !== "translation-started") {
|
|
49
|
+
setTranslationProgress((prev) => {
|
|
50
|
+
const next = new Map(prev);
|
|
51
|
+
next.delete(message.payload.language);
|
|
52
|
+
return next;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
57
|
if (message.type === "translation-progress") {
|
|
@@ -57,11 +65,17 @@ export function TranslationSidebar() {
|
|
|
57
65
|
});
|
|
58
66
|
return removeSocketMessageListener;
|
|
59
67
|
}, [editContext, setTranslationProgress]);
|
|
60
|
-
const languageData = languages.map((x) =>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
const languageData = languages.map((x) => {
|
|
69
|
+
const progress = translationProgress.get(x.languageCode);
|
|
70
|
+
const status = translationStatus?.find((y) => y.targetLanguage === x.languageCode);
|
|
71
|
+
// If we have live progress, treat it as In Progress even if the DB doesn't know yet
|
|
72
|
+
const effectiveStatus = progress ? "In Progress" : status?.status;
|
|
73
|
+
return {
|
|
74
|
+
...x,
|
|
75
|
+
translationStatus: status ? { ...status, status: effectiveStatus } : (progress ? { status: "In Progress" } : undefined),
|
|
76
|
+
translationProgress: progress,
|
|
77
|
+
};
|
|
78
|
+
});
|
|
65
79
|
languageData.sort((a, b) => {
|
|
66
80
|
// Sort languages with 0 versions to bottom
|
|
67
81
|
if (a.versions === 0 && b.versions > 0)
|
|
@@ -71,25 +85,29 @@ export function TranslationSidebar() {
|
|
|
71
85
|
// Sort by name for languages that both have versions or both don't
|
|
72
86
|
return a.name.localeCompare(b.name);
|
|
73
87
|
});
|
|
74
|
-
return (_jsxs("div", { className: "flex h-full flex-col
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
88
|
+
return (_jsxs("div", { className: "flex h-full flex-col", "data-testid": "translation-sidebar", children: [_jsx("div", { className: "flex items-center justify-end border-b border-[var(--color-gray-3)] p-1 px-2", children: item && (_jsxs(Button, { size: "xs", variant: "ghost", className: "text-theme-secondary hover:text-theme-secondary/80 hover:bg-theme-secondary-light font-semibold", "data-testid": "translation-sidebar-localize-button", onClick: () => {
|
|
89
|
+
editContext.executeCommand({
|
|
90
|
+
command: localizeItemCommand,
|
|
91
|
+
data: {
|
|
92
|
+
items: [item],
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}, children: [_jsx("i", { className: "pi pi-plus" }), "Translate"] })) }), _jsx("div", { className: "relative flex-1", children: _jsx("div", { className: "absolute inset-0 overflow-y-auto", children: _jsx(SimpleTable, { "data-testid": "translation-sidebar-language-table", columns: [
|
|
82
96
|
{ header: "Language", body: languageName },
|
|
83
|
-
{ header: "Ver.", body: (x) => x.versions.toString() },
|
|
97
|
+
{ header: "Ver.", body: (x) => _jsx("span", { className: "text-[var(--color-gray-1)]", children: x.versions.toString() }) },
|
|
84
98
|
{
|
|
85
99
|
header: "Src",
|
|
86
|
-
body: (x) => x.translationStatus?.sourceLanguage,
|
|
100
|
+
body: (x) => _jsx("span", { className: "text-[var(--color-gray-2)]", children: x.translationStatus?.sourceLanguage }),
|
|
87
101
|
},
|
|
88
102
|
{
|
|
89
103
|
header: "Status",
|
|
90
|
-
body: (x) => (_jsxs("div", { className: "flex items-center gap-2", "data-testid": `translation-status-${x.languageCode}`, children: [x.translationStatus?.status === "In Progress" && (_jsxs("div", { className: "relative w-full", children: [_jsx(Progress, { className: "h-5", value: (x.translationProgress?.progress || 0) * 100, showValue: false, "data-testid": `translation-progress-${x.languageCode}` }), _jsx("div", { className: "absolute inset-0 flex items-center justify-center text-white text-xs", children: x.translationProgress?.message })] })), x.translationStatus?.status !== "In Progress" && (_jsx("
|
|
104
|
+
body: (x) => (_jsxs("div", { className: "flex items-center gap-2", "data-testid": `translation-status-${x.languageCode}`, children: [x.translationStatus?.status === "In Progress" && (_jsxs("div", { className: "relative w-full", children: [_jsx(Progress, { className: "h-5", value: (x.translationProgress?.progress || 0) * 100, showValue: false, indicatorClassName: "bg-[#9650fb]", "data-testid": `translation-progress-${x.languageCode}` }), _jsx("div", { className: "absolute inset-0 flex items-center justify-center text-white text-xs font-medium", children: x.translationProgress?.message })] })), x.translationStatus?.status !== "In Progress" && (_jsx("span", { title: x.translationStatus?.message, className: x.translationStatus?.status === "Completed"
|
|
105
|
+
? "text-green-600 font-medium"
|
|
106
|
+
: x.translationStatus?.status === "Error"
|
|
107
|
+
? "text-red-600 font-medium"
|
|
108
|
+
: "text-[var(--color-gray-2)]", children: x.translationStatus?.status || "Not started" }))] })),
|
|
91
109
|
},
|
|
92
110
|
], items: languageData, onRowClick: (data) => selectLanguage(data.item), rowClassName: (item) => item.languageCode == editContext.currentItemDescriptor?.language
|
|
93
|
-
? "bg-
|
|
111
|
+
? "bg-[#f6eeff]"
|
|
94
112
|
: "" }) }) })] }));
|
|
95
113
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MetadataInputStep.d.ts","sourceRoot":"","sources":["../../src/steps/MetadataInputStep.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE/C,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,QAAe,EACf,IAAI,EACJ,OAAO,EACP,eAAe,GAChB,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"MetadataInputStep.d.ts","sourceRoot":"","sources":["../../src/steps/MetadataInputStep.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE/C,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,QAAe,EACf,IAAI,EACJ,OAAO,EACP,eAAe,GAChB,EAAE,oBAAoB,2CA8EtB"}
|
|
@@ -37,5 +37,5 @@ export function MetadataInputStep({ stepIndex, isActive = true, data, setData, o
|
|
|
37
37
|
onStepCompleted(true);
|
|
38
38
|
}, [isActive, onStepCompleted]); // Check when active state changes
|
|
39
39
|
// No footer actions needed since data is saved automatically
|
|
40
|
-
return (_jsxs("div", { className: "flex flex-col gap-4 p-
|
|
40
|
+
return (_jsxs("div", { className: "flex flex-col gap-4 p-6", "data-testid": "metadata-input-step", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-xl font-semibold text-[var(--color-dark)] mb-2", children: "Enter Metadata Per Item Per Language" }), _jsx("p", { className: "text-sm text-[var(--color-gray-2)]", children: "Provide custom metadata for each item and language combination (optional)." })] }), _jsx("div", { className: "max-h-64 overflow-y-auto space-y-4", "data-testid": "metadata-input-container", children: allItems.map((item) => (_jsxs("div", { className: "border border-[var(--color-gray-3)] rounded-lg p-4 bg-background shadow-sm", "data-testid": `metadata-item-${item.id}`, children: [_jsx("label", { className: "block text-sm font-medium text-[var(--color-dark)] mb-3", "data-testid": `metadata-item-label-${item.id}`, children: item.name || item.id }), data.targetLanguages?.map((language) => (_jsxs("div", { className: "mb-3", "data-testid": `metadata-field-${item.id}-${language}`, children: [_jsxs("label", { className: "block text-xs font-medium mb-1.5 text-[var(--color-gray-2)]", "data-testid": `metadata-language-label-${item.id}-${language}`, children: [language.toUpperCase(), ":"] }), _jsx("textarea", { className: "w-full border border-[var(--color-gray-3)] rounded-md p-2.5 text-sm bg-[var(--color-gray-5)] text-[var(--color-dark)] focus:outline-none focus:ring-2 focus:ring-[#9650fb] focus:border-[#9650fb] transition-colors", rows: 2, value: itemMetadata[item.id]?.[language] || "", onChange: (e) => handleMetadataChange(item.id, language, e.target.value), placeholder: `Enter metadata for ${language}...`, "data-testid": `metadata-textarea-${item.id}-${language}` })] }, `${item.id}-${language}`)))] }, item.id))) })] }));
|
|
41
41
|
}
|
|
@@ -94,9 +94,9 @@ export function PromptCustomizationStep({ stepIndex, isActive = true, data, setD
|
|
|
94
94
|
}, [isActive, onStepCompleted]);
|
|
95
95
|
// Skip condition: hide step when checkbox is disabled
|
|
96
96
|
// This is handled by skipCondition in wizard config
|
|
97
|
-
return (_jsxs("div", { className: "p-6 space-y-6 h-full flex flex-col", "data-testid": "prompt-customization-step", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-xl font-semibold mb-2", children: "Customize Translation Prompt" }), _jsxs("p", { className: "text-sm text-gray-
|
|
97
|
+
return (_jsxs("div", { className: "p-6 space-y-6 h-full flex flex-col", "data-testid": "prompt-customization-step", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-xl font-semibold text-[var(--color-dark)] mb-2", children: "Customize Translation Prompt" }), _jsxs("p", { className: "text-sm text-[var(--color-gray-2)] mb-6", children: ["Optionally customize the prompt used for translation. This allows you to provide specific instructions or context for the translation service.", _jsx("br", {}), _jsx("span", { className: "text-xs text-[var(--color-gray-2)] mt-1 block", children: "Note: Your custom prompt will be appended to the system instructions that ensure proper translation structure." })] })] }), _jsxs("div", { className: "space-y-6 flex-1", children: [!enableCustomPrompt && (_jsx("div", { className: "border border-[var(--color-gray-3)] rounded-lg p-4 bg-[var(--color-gray-5)]", children: _jsx("p", { className: "text-sm text-[var(--color-gray-2)]", children: "Enable \"Customize translation prompt\" in the previous step to customize the prompt." }) })), enableCustomPrompt && (_jsxs(_Fragment, { children: [hasDefaultPrompt && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "bg-background rounded-lg border border-[var(--color-gray-3)] p-4", children: [_jsx("h3", { className: "text-sm font-medium text-[var(--color-dark)] mb-2", children: "Default Prompt" }), _jsx("div", { className: "border border-[var(--color-gray-3)] rounded-md p-3 bg-[var(--color-gray-5)]", children: _jsx("pre", { className: "text-xs text-[var(--color-gray-1)] whitespace-pre-wrap font-mono", children: defaultPrompt }) })] }), _jsxs("div", { className: "bg-background rounded-lg border border-[var(--color-gray-3)] p-4", children: [_jsx("h3", { className: "text-sm font-medium text-[var(--color-dark)] mb-3", children: "Customization Type" }), _jsxs("div", { className: "space-y-3", children: [_jsxs("label", { className: "flex items-center cursor-pointer py-1.5 px-2 rounded-md hover:bg-[var(--color-gray-5)] transition-colors", children: [_jsx("input", { type: "radio", name: "customizationType", value: "extend", checked: customizationType === "extend", onChange: () => setCustomizationType("extend"), className: "h-4 w-4 text-[#9650fb] focus:ring-[#9650fb] border-[var(--color-gray-3)] accent-[#9650fb]", "data-testid": "customization-type-extend" }), _jsx("span", { className: "ml-2 text-sm text-[var(--color-dark)]", children: "Extend (append to default)" })] }), _jsxs("label", { className: "flex items-center cursor-pointer py-1.5 px-2 rounded-md hover:bg-[var(--color-gray-5)] transition-colors", children: [_jsx("input", { type: "radio", name: "customizationType", value: "replace", checked: customizationType === "replace", onChange: () => setCustomizationType("replace"), className: "h-4 w-4 text-[#9650fb] focus:ring-[#9650fb] border-[var(--color-gray-3)] accent-[#9650fb]", "data-testid": "customization-type-replace" }), _jsx("span", { className: "ml-2 text-sm text-[var(--color-dark)]", children: "Replace (use custom prompt only)" })] })] })] })] })), _jsxs("div", { className: "bg-background rounded-lg border border-[var(--color-gray-3)] p-4", children: [_jsx("h3", { className: "text-sm font-medium text-[var(--color-dark)] mb-2", children: "Custom Prompt" }), _jsx("textarea", { value: customPrompt, onChange: (e) => setCustomPrompt(e.target.value), className: "w-full px-3 py-2.5 border border-[var(--color-gray-3)] rounded-md bg-[var(--color-gray-5)] text-[var(--color-dark)] focus:outline-none focus:ring-2 focus:ring-[#9650fb] focus:border-[#9650fb] text-sm font-mono transition-colors", rows: 6, placeholder: "Enter your custom prompt instructions here...", "data-testid": "custom-prompt-textarea" }), _jsx("p", { className: "text-xs text-[var(--color-gray-2)] mt-2", children: hasDefaultPrompt
|
|
98
98
|
? customizationType === "extend"
|
|
99
99
|
? "This will be appended to the default prompt. The final prompt (default + custom) will then be appended to the system instructions on the backend."
|
|
100
100
|
: "This will replace the default prompt. The custom prompt will then be appended to the system instructions on the backend."
|
|
101
|
-
: "Your custom prompt will be appended to the system instructions on the backend." })] }), hasDefaultPrompt && _jsxs("div", { children: [_jsx("h3", { className: "text-sm font-medium text-
|
|
101
|
+
: "Your custom prompt will be appended to the system instructions on the backend." })] }), hasDefaultPrompt && _jsxs("div", { className: "bg-background rounded-lg border border-[var(--color-gray-3)] p-4", children: [_jsx("h3", { className: "text-sm font-medium text-[var(--color-dark)] mb-2", children: "Preview" }), _jsx("div", { className: "border border-[var(--color-gray-3)] rounded-md p-3 bg-[var(--color-gray-5)] max-h-64 overflow-y-auto", children: _jsx("pre", { className: "text-xs text-[var(--color-gray-1)] whitespace-pre-wrap font-mono", children: previewPrompt }) }), _jsx("p", { className: "text-xs text-[var(--color-gray-2)] mt-2", children: "This is how the final prompt will look when sent to the translation service." })] })] }))] })] }));
|
|
102
102
|
}
|
|
@@ -186,7 +186,7 @@ export function ServiceLanguageSelectionStep({ stepIndex, isActive = true, data,
|
|
|
186
186
|
const serviceData = data.serviceCustomData?.get("OpenAI");
|
|
187
187
|
return serviceData?.enableCustomPrompt === true;
|
|
188
188
|
}, [data.translationProvider, data.serviceCustomData]);
|
|
189
|
-
return (_jsxs("div", { className: "p-6 space-y-6 h-full flex flex-col", "data-testid": "service-language-selection-step", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-xl font-semibold mb-2", children: "Configure Translation" }), _jsx("p", { className: "text-sm text-gray-
|
|
189
|
+
return (_jsxs("div", { className: "p-6 space-y-6 h-full flex flex-col", "data-testid": "service-language-selection-step", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-xl font-semibold text-[var(--color-dark)] mb-2", children: "Configure Translation" }), _jsx("p", { className: "text-sm text-[var(--color-gray-2)] mb-6", children: "Select translation provider and target languages for your content." })] }), _jsxs("div", { className: "space-y-6 flex-1", children: [_jsxs("div", { className: "bg-background rounded-lg border border-[var(--color-gray-3)] p-4", children: [_jsx("h3", { className: "text-sm font-medium text-[var(--color-dark)] mb-2", children: "Translation Provider" }), _jsx("p", { className: "text-xs text-[var(--color-gray-2)] mb-3", children: "Choose how to translate your content. \"Create Versions\" will create new language versions without automatic translation." }), _jsxs("select", { value: data.translationProvider || "", onChange: handleProviderChange, className: "block w-full px-3 py-2 border border-[var(--color-gray-3)] rounded-md bg-[var(--color-gray-5)] text-[var(--color-dark)] text-sm focus:outline-none focus:ring-2 focus:ring-[#9650fb] focus:border-[#9650fb] transition-colors", "data-testid": "translation-provider-select", children: [_jsx("option", { value: "", disabled: true, children: "Select a provider..." }), data.translationProviders.map((provider) => (_jsx("option", { value: provider.name, children: provider.displayName || provider.name }, provider.name)))] })] }), multiItemEnabled && (_jsxs("div", { className: "bg-background rounded-lg border border-[var(--color-gray-3)] p-4", children: [_jsxs("label", { className: "flex items-center cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: data.includeSubitems, onChange: handleSubitemsToggle, className: "h-4 w-4 text-[#9650fb] focus:ring-[#9650fb] border-[var(--color-gray-3)] rounded accent-[#9650fb]", "data-testid": "include-subitems-checkbox" }), _jsx("span", { className: "ml-2 text-sm text-[var(--color-dark)] font-medium", children: "Include subitems" })] }), _jsx("p", { className: "text-xs text-[var(--color-gray-2)] mt-1.5 ml-6", children: "Also translate any child components and nested content within this item." })] })), data.translationProvider === "OpenAI" && (_jsxs("div", { className: "bg-background rounded-lg border border-[var(--color-gray-3)] p-4", children: [_jsxs("label", { className: "flex items-center cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: isPromptCustomizationEnabled, onChange: (e) => {
|
|
190
190
|
const isChecked = e.target.checked;
|
|
191
191
|
// Always create a new Map instance to ensure React detects the change
|
|
192
192
|
const newServiceCustomData = new Map();
|
|
@@ -211,11 +211,11 @@ export function ServiceLanguageSelectionStep({ stepIndex, isActive = true, data,
|
|
|
211
211
|
serviceCustomData: newServiceCustomData
|
|
212
212
|
};
|
|
213
213
|
setData(newData);
|
|
214
|
-
}, className: "h-4 w-4 text-
|
|
214
|
+
}, className: "h-4 w-4 text-[#9650fb] focus:ring-[#9650fb] border-[var(--color-gray-3)] rounded accent-[#9650fb]", "data-testid": "enable-custom-prompt-checkbox" }), _jsx("span", { className: "ml-2 text-sm text-[var(--color-dark)] font-medium", children: "Customize translation prompt" })] }), _jsx("p", { className: "text-xs text-[var(--color-gray-2)] mt-1.5 ml-6", children: "Enable advanced prompt customization for the translation service." })] })), _jsxs("div", { className: "bg-background rounded-lg border border-[var(--color-gray-3)] p-4", children: [_jsxs("div", { className: "flex items-center justify-between mb-2", children: [_jsx("h3", { className: "text-sm font-medium text-[var(--color-dark)]", children: "Target Languages" }), allLanguages.length > 1 && (_jsxs("label", { className: "flex items-center cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: areAllLanguagesSelected, ref: (input) => {
|
|
215
215
|
if (input) {
|
|
216
216
|
input.indeterminate = areSomeLanguagesSelected && !areAllLanguagesSelected;
|
|
217
217
|
}
|
|
218
|
-
}, onChange: handleSelectAllLanguages, className: "h-4 w-4 text-
|
|
218
|
+
}, onChange: handleSelectAllLanguages, className: "h-4 w-4 text-[#9650fb] focus:ring-[#9650fb] border-[var(--color-gray-3)] rounded accent-[#9650fb]", "data-testid": "select-all-languages-checkbox" }), _jsx("span", { className: "ml-2 text-xs text-[var(--color-gray-2)]", children: "Select All" })] }))] }), _jsx("p", { className: "text-xs text-[var(--color-gray-2)] mb-3", children: "Select the languages you want to translate this content into." }), _jsx("div", { className: "border border-[var(--color-gray-3)] rounded-lg min-h-[200px] max-h-64 overflow-y-auto bg-[var(--color-gray-5)]", children: data.translationProviders.length === 0 || allLanguages.length === 0 ? (
|
|
219
219
|
// Loading skeleton
|
|
220
|
-
_jsx("div", { className: "p-3 space-y-2", children: [...Array(4)].map((_, i) => (_jsxs("div", { className: "flex items-center animate-pulse", children: [_jsx("div", { className: "h-4 w-4 bg-gray-
|
|
220
|
+
_jsx("div", { className: "p-3 space-y-2", children: [...Array(4)].map((_, i) => (_jsxs("div", { className: "flex items-center animate-pulse", children: [_jsx("div", { className: "h-4 w-4 bg-[var(--color-gray-3)] rounded" }), _jsx("div", { className: "ml-2 h-4 bg-[var(--color-gray-3)] rounded w-32" }), _jsx("div", { className: "ml-auto h-4 bg-[var(--color-gray-3)] rounded w-16" })] }, i))) })) : (_jsx("div", { className: "p-3 grid grid-cols-1 gap-2", children: allLanguages.map((lang) => (_jsxs("label", { className: "flex items-center py-1.5 px-2 rounded-md hover:bg-[var(--color-gray-4)] transition-colors cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: languageSelection[lang.code] || false, onChange: () => handleLanguageToggle(lang.code), className: "h-4 w-4 text-[#9650fb] focus:ring-[#9650fb] border-[var(--color-gray-3)] rounded accent-[#9650fb]", "data-testid": `language-checkbox-${lang.code}` }), _jsxs("span", { className: "ml-2 text-sm text-[var(--color-dark)] flex items-center gap-2", children: [_jsxs("span", { children: [lang.name, " (", lang.code, ")"] }), lang.sourceLanguage && (_jsxs("span", { className: "text-xs text-[var(--color-gray-2)]", children: ["from: ", lang.sourceLanguage] }))] }), !lang.hasVersions && (_jsx("span", { className: "ml-auto text-2xs text-orange-600 bg-orange-100 px-2 py-1 rounded-full font-medium", children: "No versions" }))] }, lang.code))) })) })] })] })] }));
|
|
221
221
|
}
|
|
@@ -4,7 +4,7 @@ import { Button, PerfectTree } from "@parhelia/core";
|
|
|
4
4
|
import { convertFullItemToStub, convertStubToFullItem } from "@parhelia/core";
|
|
5
5
|
import { discoverItemsTree, convertBackendTreeToTreeNodes, flattenPagesFromBackendTrees } from "../api/discovery";
|
|
6
6
|
// We need to implement a basic Spinner component since it's not in core
|
|
7
|
-
const Spinner = ({ ...props }) => (_jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-
|
|
7
|
+
const Spinner = ({ ...props }) => (_jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-[#9650fb]", ...props }));
|
|
8
8
|
export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData, editContext, onStepCompleted, setBeforeNextCallback, setFooterActions, requestClose }) {
|
|
9
9
|
// Core state - simplified
|
|
10
10
|
const [isDiscovering, setIsDiscovering] = useState(false);
|
|
@@ -264,9 +264,9 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
|
|
|
264
264
|
setIsDiscovering(false);
|
|
265
265
|
setDiscoveryComplete(true);
|
|
266
266
|
};
|
|
267
|
-
return (_jsxs("div", { className: "flex flex-col gap-4 p-6 h-full", "data-testid": "subitem-discovery-step", children: [_jsxs("div", { className: "mb-2", children: [_jsx("h3", { className: "text-lg font-
|
|
267
|
+
return (_jsxs("div", { className: "flex flex-col gap-4 p-6 h-full", "data-testid": "subitem-discovery-step", children: [_jsxs("div", { className: "mb-2", children: [_jsx("h3", { className: "text-lg font-semibold text-[var(--color-dark)] mb-1", children: "Discover Subitems" }), _jsx("p", { className: "text-sm text-[var(--color-gray-2)]", children: "Scanning for subitems to include in translation..." })] }), _jsxs("div", { className: "border border-[var(--color-gray-3)] rounded-lg p-4 bg-background min-h-[120px] shadow-sm", "data-testid": "discovery-status-container", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [isDiscovering && _jsx(Spinner, { "data-testid": "discovery-spinner" }), _jsx("span", { className: "font-medium text-[var(--color-dark)]", "data-testid": "discovery-status-text", children: isDiscovering ? 'Discovering subitems...' :
|
|
268
268
|
discoveryComplete ? 'Discovery Complete' :
|
|
269
|
-
'Ready to discover' })] }), isDiscovering && (_jsx(Button, { size: "sm", onClick: handleCancel, "data-testid": "discovery-cancel-button", children: "Cancel" }))] }), _jsx("div", { className: "text-sm text-gray-
|
|
269
|
+
'Ready to discover' })] }), isDiscovering && (_jsx(Button, { size: "sm", variant: "outline", onClick: handleCancel, "data-testid": "discovery-cancel-button", children: "Cancel" }))] }), _jsx("div", { className: "text-sm text-[var(--color-gray-2)] mb-3", "data-testid": "discovery-summary", children: discoveredCount > 0 ? (_jsxs("p", { "data-testid": "discovery-total-count", children: [_jsxs("span", { className: "font-medium text-[#9650fb]", children: [totalItemsCount, " total items found"] }), totalItemsCount !== translatableItemsCount && (_jsxs(_Fragment, { children: [_jsx("br", {}), _jsxs("span", { className: "text-xs text-[var(--color-gray-2)]", children: ["Translatable items: ", translatableItemsCount, " | Non-translatable: ", totalItemsCount - translatableItemsCount] })] })), _jsx("br", {}), _jsxs("span", { className: "text-xs text-[var(--color-gray-2)]", children: ["Original items: ", data.items.length, " | Subitems discovered: ", Math.max(0, totalItemsCount - data.items.length)] }), isDiscovering && (_jsxs(_Fragment, { children: [_jsx("br", {}), _jsx("span", { className: "text-xs text-[var(--color-gray-2)] italic", children: "Item tree will appear when discovery completes" })] }))] })) : (_jsx("p", { className: "text-[var(--color-gray-2)]", children: "No items discovered yet." })) }), _jsx("div", { className: "mt-4 min-h-[400px]", children: !isDiscovering && discoveryComplete && treeInitialized && allDiscoveredItems.length > 0 && treeNodes.length > 0 ? (_jsx("div", { children: _jsxs("div", { className: "border-t border-[var(--color-gray-3)] pt-4", "data-testid": "item-selection-section", children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsx("h3", { className: "text-lg font-semibold text-[var(--color-dark)]", children: "Select Items to Translate" }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx("span", { className: "text-sm text-[var(--color-gray-2)]", "data-testid": "selection-summary-header", children: selectedItemIds.size > 0 ? _jsxs(_Fragment, { children: [_jsx("span", { className: "font-medium text-[#9650fb]", children: selectedItemIds.size }), " selected"] }) : "No items selected" }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
270
270
|
if (!isActive)
|
|
271
271
|
return;
|
|
272
272
|
// Only select translatable items
|
|
@@ -284,13 +284,13 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
|
|
|
284
284
|
setUserHasInteracted(true);
|
|
285
285
|
setSelectedItemIds(translatableIds);
|
|
286
286
|
onStepCompleted(translatableIds.size > 0);
|
|
287
|
-
}, "data-testid": "select-all-items-button", children: "Select All" }), _jsx(Button, { size: "sm", variant: "
|
|
287
|
+
}, "data-testid": "select-all-items-button", children: "Select All" }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => {
|
|
288
288
|
if (!isActive)
|
|
289
289
|
return;
|
|
290
290
|
setUserHasInteracted(true);
|
|
291
291
|
setSelectedItemIds(new Set());
|
|
292
292
|
onStepCompleted(false);
|
|
293
|
-
}, "data-testid": "select-none-items-button", children: "Select None" })] })] }), _jsx("div", { className: "text-
|
|
293
|
+
}, "data-testid": "select-none-items-button", children: "Select None" })] })] }), _jsx("div", { className: "text-xs text-[var(--color-gray-2)] mb-3", "data-testid": "selection-summary", children: _jsx("span", { children: "Tip: Hold Shift and click a checkbox to toggle all descendants." }) }), treeNodes.length > 0 && (_jsx("div", { className: "border border-[var(--color-gray-3)] rounded-lg h-80 overflow-auto bg-[var(--color-gray-5)]", "data-testid": "item-tree-view", children: _jsx(PerfectTree, { nodes: treeNodes, expandedKeys: expandedKeys, selectedKeys: selectedKeys, onToggleExpand: (key) => {
|
|
294
294
|
setExpandedIds(prev => {
|
|
295
295
|
const next = new Set(prev);
|
|
296
296
|
if (next.has(key))
|
|
@@ -389,7 +389,7 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
|
|
|
389
389
|
} }), _jsx("span", { className: `${!isTranslatable ? 'opacity-70 italic' : ''}`, children: node.label })] }));
|
|
390
390
|
} }) }))] }) })) : isDiscovering ? (
|
|
391
391
|
// Loading skeleton for discovery results
|
|
392
|
-
_jsxs("div", { children: [_jsx("div", { className: "p-3 bg-
|
|
392
|
+
_jsxs("div", { children: [_jsx("div", { className: "p-3 bg-[#f6eeff] border border-[#9650fb]/20 rounded-lg mb-4", children: _jsx("div", { className: "h-4 bg-[#9650fb]/20 rounded w-64 animate-pulse" }) }), _jsxs("div", { className: "border-t border-[var(--color-gray-3)] pt-4", children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsx("div", { className: "h-6 bg-[var(--color-gray-3)] rounded w-48 animate-pulse" }), _jsxs("div", { className: "flex gap-2", children: [_jsx("div", { className: "h-8 bg-[var(--color-gray-3)] rounded w-20 animate-pulse" }), _jsx("div", { className: "h-8 bg-[var(--color-gray-3)] rounded w-20 animate-pulse" })] })] }), _jsx("div", { className: "h-4 bg-[var(--color-gray-3)] rounded w-64 mb-3 animate-pulse" }), _jsx("div", { className: "border border-[var(--color-gray-3)] rounded-lg h-80 overflow-auto bg-[var(--color-gray-5)]", children: _jsx("div", { className: "p-3 space-y-2", children: [...Array(8)].map((_, i) => (_jsxs("div", { className: "flex items-center gap-3 animate-pulse", children: [_jsx("div", { className: "h-4 w-4 bg-[var(--color-gray-3)] rounded" }), _jsx("div", { className: "h-4 bg-[var(--color-gray-3)] rounded w-48" })] }, i))) }) })] })] })) : (
|
|
393
393
|
// Empty state
|
|
394
|
-
_jsx("div", { className: "flex items-center justify-center h-80 border rounded-lg bg-gray-
|
|
394
|
+
_jsx("div", { className: "flex items-center justify-center h-80 border border-[var(--color-gray-3)] rounded-lg bg-[var(--color-gray-5)]", children: _jsxs("div", { className: "text-center text-[var(--color-gray-2)]", children: [_jsx("p", { className: "font-medium text-[var(--color-gray-1)]", children: "Ready to discover subitems" }), _jsx("p", { className: "text-sm mt-1", children: "Discovery will start automatically" })] }) })) })] })] }));
|
|
395
395
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BatchTranslationView.d.ts","sourceRoot":"","sources":["../../src/translation-center/BatchTranslationView.tsx"],"names":[],"mappings":"AAwBA,OAAO,qCAAqC,CAAC;AAa7C,UAAU,yBAAyB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAoCD,wBAAgB,oBAAoB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,yBAAyB,
|
|
1
|
+
{"version":3,"file":"BatchTranslationView.d.ts","sourceRoot":"","sources":["../../src/translation-center/BatchTranslationView.tsx"],"names":[],"mappings":"AAwBA,OAAO,qCAAqC,CAAC;AAa7C,UAAU,yBAAyB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAoCD,wBAAgB,oBAAoB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,yBAAyB,2CAq8BlF"}
|