@parhelia/localization 0.1.12906 → 0.1.12909
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/LocalizeItemCommand.d.ts +7 -1
- package/dist/LocalizeItemCommand.d.ts.map +1 -1
- package/dist/LocalizeItemCommand.js +31 -18
- package/dist/LocalizeItemDialog.d.ts.map +1 -1
- package/dist/LocalizeItemDialog.js +97 -35
- package/dist/LocalizeItemUtils.d.ts +1 -2
- package/dist/LocalizeItemUtils.d.ts.map +1 -1
- package/dist/LocalizeItemUtils.js +78 -36
- package/dist/api/discovery.d.ts +25 -0
- package/dist/api/discovery.d.ts.map +1 -1
- package/dist/api/discovery.js +106 -2
- package/dist/hooks/useTranslationWizard.d.ts.map +1 -1
- package/dist/hooks/useTranslationWizard.js +3 -3
- package/dist/index.d.ts +10 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -32
- package/dist/services/translationService.d.ts +41 -10
- package/dist/services/translationService.d.ts.map +1 -1
- package/dist/services/translationService.js +48 -6
- package/dist/settings/TranslationServicesPanel.d.ts.map +1 -1
- package/dist/settings/TranslationServicesPanel.js +21 -36
- package/dist/setup/LocalizationSetupStep.d.ts.map +1 -1
- package/dist/setup/LocalizationSetupStep.js +29 -18
- package/dist/sidebar/TranslationSidebar.d.ts.map +1 -1
- package/dist/sidebar/TranslationSidebar.js +20 -10
- package/dist/steps/ItemSelectionStep.d.ts +3 -0
- package/dist/steps/ItemSelectionStep.d.ts.map +1 -0
- package/dist/steps/ItemSelectionStep.js +24 -0
- package/dist/steps/ItemSelectionTree.d.ts +13 -0
- package/dist/steps/ItemSelectionTree.d.ts.map +1 -0
- package/dist/steps/ItemSelectionTree.js +327 -0
- package/dist/steps/PromptCustomizationStep.d.ts +1 -1
- package/dist/steps/PromptCustomizationStep.d.ts.map +1 -1
- package/dist/steps/PromptCustomizationStep.js +159 -56
- package/dist/steps/ServiceLanguageSelectionStep.d.ts +6 -1
- package/dist/steps/ServiceLanguageSelectionStep.d.ts.map +1 -1
- package/dist/steps/ServiceLanguageSelectionStep.js +92 -165
- package/dist/steps/WizardStepShell.d.ts +17 -0
- package/dist/steps/WizardStepShell.d.ts.map +1 -0
- package/dist/steps/WizardStepShell.js +11 -0
- package/dist/steps/types.d.ts +17 -1
- package/dist/steps/types.d.ts.map +1 -1
- package/dist/translation-center/TranslationBatches.d.ts +2 -0
- package/dist/translation-center/TranslationBatches.d.ts.map +1 -0
- package/dist/translation-center/TranslationBatches.js +1180 -0
- package/dist/translation-center/TranslationManagement.d.ts.map +1 -1
- package/dist/translation-center/TranslationManagement.js +25 -15
- package/dist/translation-center/TranslationsTitlebar.d.ts +6 -0
- package/dist/translation-center/TranslationsTitlebar.d.ts.map +1 -0
- package/dist/translation-center/TranslationsTitlebar.js +25 -0
- package/dist/translationEvents.d.ts +6 -0
- package/dist/translationEvents.d.ts.map +1 -0
- package/dist/translationEvents.js +4 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/constants.d.ts +0 -15
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -21
- package/dist/steps/MetadataInputStep.d.ts +0 -4
- package/dist/steps/MetadataInputStep.d.ts.map +0 -1
- package/dist/steps/MetadataInputStep.js +0 -41
- package/dist/steps/SubitemDiscoveryStep.d.ts +0 -3
- package/dist/steps/SubitemDiscoveryStep.d.ts.map +0 -1
- package/dist/steps/SubitemDiscoveryStep.js +0 -313
- package/dist/steps/index.d.ts +0 -5
- package/dist/steps/index.d.ts.map +0 -1
- package/dist/steps/index.js +0 -4
- package/dist/translation-center/BatchTranslationView.d.ts +0 -8
- package/dist/translation-center/BatchTranslationView.d.ts.map +0 -1
- package/dist/translation-center/BatchTranslationView.js +0 -870
- package/dist/translation-center/RecentTranslations.d.ts +0 -2
- package/dist/translation-center/RecentTranslations.d.ts.map +0 -1
- package/dist/translation-center/RecentTranslations.js +0 -309
- package/dist/utils/createVersions.d.ts +0 -14
- package/dist/utils/createVersions.d.ts.map +0 -1
- package/dist/utils/createVersions.js +0 -26
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
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,
|
|
3
|
+
import { Button, Card, useEditContext, Splitter, ItemConfigPanel, DeleteIcon, } from "@parhelia/core";
|
|
4
|
+
import { CheckCircle as LucideCheckCircle, AlertCircle as LucideAlertCircle, RefreshCw as LucideRefreshCw, Plus as LucidePlus, Settings as LucideSettings, Languages as LucideLanguages, ListChecks as LucideListChecks, } from "lucide-react";
|
|
5
5
|
import { getAvailableTranslationServices, createProviderSettings, getTranslationStructure, ensureTranslationStructure, } from "../services/translationService";
|
|
6
6
|
const CheckCircleIcon = LucideCheckCircle;
|
|
7
7
|
const AlertCircleIcon = LucideAlertCircle;
|
|
8
8
|
const RefreshCwIcon = LucideRefreshCw;
|
|
9
9
|
const PlusIcon = LucidePlus;
|
|
10
10
|
const SettingsIcon = LucideSettings;
|
|
11
|
-
const
|
|
11
|
+
const LanguagesIcon = LucideLanguages;
|
|
12
|
+
const ListChecksIcon = LucideListChecks;
|
|
12
13
|
const DEFAULT_STRUCTURE_SETTINGS = {
|
|
13
14
|
translationFolderPath: "/sitecore/system/Parhelia/Settings/Translation",
|
|
14
15
|
translationFolderTemplateId: "b1e40cfe-6e36-4a0e-a49e-19c10b2127b7",
|
|
@@ -236,46 +237,30 @@ export function TranslationServicesPanel() {
|
|
|
236
237
|
useEffect(() => {
|
|
237
238
|
loadData();
|
|
238
239
|
}, [loadData]);
|
|
239
|
-
const statusIcon = (currentState) => {
|
|
240
|
-
if (currentState === "success")
|
|
241
|
-
return (_jsx(CheckCircleIcon, { className: "h-4 w-4 text-green-600", strokeWidth: 1 }));
|
|
242
|
-
if (currentState === "error")
|
|
243
|
-
return (_jsx(AlertCircleIcon, { className: "h-4 w-4 text-red-600", strokeWidth: 1 }));
|
|
244
|
-
return (_jsx(RefreshCwIcon, { className: "h-4 w-4 animate-spin text-amber-600", strokeWidth: 1 }));
|
|
245
|
-
};
|
|
246
240
|
const configuredCount = services.filter((s) => s.isConfigured).length;
|
|
247
241
|
const totalCount = services.length;
|
|
248
242
|
const translationFolderExists = !!structureState?.translationFolder?.exists;
|
|
249
243
|
const providersFolderExists = !!structureState?.translationProvidersFolder?.exists;
|
|
250
244
|
// Build the services list content
|
|
251
|
-
const servicesListContent = (
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
: "ghost", onClick: () => handleOpenStructureConfig(structureState.translationFolder.itemId, "Configure: Translation folder"), className: "shrink-0", children: [_jsx(SettingsIcon, { className: "h-4 w-4", strokeWidth: 1.5 }), editContext?.isMobile ? "" : "Configure"] })) })] }), _jsxs("div", { "data-testid": "translation-structure-providers-folder", className: `flex items-center justify-between rounded border p-3 text-sm transition-shadow hover:shadow-sm ${selectedConfigTarget?.key ===
|
|
261
|
-
`structure:${structureState?.translationProvidersFolder?.itemId}`
|
|
262
|
-
? "border-blue-400 bg-blue-50"
|
|
263
|
-
: "border-gray-200 bg-white"}`, children: [_jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [providersFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 text-green-600 shrink-0", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 text-amber-500 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 shrink-0", children: providersFolderExists &&
|
|
264
|
-
structureState?.translationProvidersFolder?.itemId && (_jsxs(Button, { size: "sm", variant: selectedConfigTarget?.key ===
|
|
265
|
-
`structure:${structureState.translationProvidersFolder.itemId}`
|
|
266
|
-
? "default"
|
|
267
|
-
: "ghost", onClick: () => handleOpenStructureConfig(structureState.translationProvidersFolder.itemId, "Configure: Translation Providers folder"), className: "shrink-0", children: [_jsx(SettingsIcon, { className: "h-4 w-4", strokeWidth: 1.5 }), editContext?.isMobile ? "" : "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
|
|
268
|
-
? `${configuredCount} of ${totalCount} service${totalCount !== 1 ? "s" : ""} configured`
|
|
269
|
-
: "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", "data-testid": "translation-services-providers", children: services.map((service) => {
|
|
245
|
+
const servicesListContent = (_jsxs("div", { className: "flex h-full flex-col gap-4 p-4", "data-testid": "translation-services-panel", children: [_jsx(Card, { icon: _jsx(ListChecksIcon, { strokeWidth: 1, className: "h-5 w-5" }), title: "Prerequisites", description: "Required Sitecore folders for translation settings.", noPadding: true, className: "shrink-0", headerActions: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex items-center gap-1.5 text-xs text-neutral-grey-50", children: translationFolderExists && providersFolderExists ? (_jsxs(_Fragment, { children: [_jsx(CheckCircleIcon, { className: "h-3.5 w-3.5 text-feedback-green", strokeWidth: 1.5 }), "All parent items found"] })) : (_jsxs(_Fragment, { children: [_jsx(AlertCircleIcon, { className: "h-3.5 w-3.5 text-feedback-orange", strokeWidth: 1.5 }), "Parent items missing"] })) }), !providersFolderExists && (_jsxs(Button, { size: "sm", variant: "default", onClick: ensureStructure, disabled: ensuringStructure || structureLoading, children: [ensuringStructure ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "mr-1 h-4 w-4 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1.75, className: "mr-1 h-4 w-4" })), "Ensure items"] }))] }), children: _jsxs("div", { className: "divide-y divide-border-default border-t border-border-default", children: [_jsxs("div", { "data-testid": "translation-structure-folder", className: `flex items-center gap-3 px-3 py-3 text-sm transition-colors ${selectedConfigTarget?.key ===
|
|
246
|
+
`structure:${structureState?.translationFolder?.itemId}`
|
|
247
|
+
? "bg-feedback-blue-light"
|
|
248
|
+
: "bg-white"}`, children: [translationFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1.5 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-neutral-grey-100", children: "Translation folder" }), _jsx("div", { className: "mt-0.5 truncate font-mono text-xs text-neutral-grey-50", children: structureSettings.translationFolderPath })] }), translationFolderExists &&
|
|
249
|
+
structureState?.translationFolder?.itemId && (_jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleOpenStructureConfig(structureState.translationFolder.itemId, "Configure: Translation folder"), title: "Configure", children: _jsx(SettingsIcon, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) }))] }), _jsxs("div", { "data-testid": "translation-structure-providers-folder", className: `flex items-center gap-3 px-3 py-3 text-sm transition-colors ${selectedConfigTarget?.key ===
|
|
250
|
+
`structure:${structureState?.translationProvidersFolder?.itemId}`
|
|
251
|
+
? "bg-feedback-blue-light"
|
|
252
|
+
: "bg-white"}`, children: [providersFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1.5 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-neutral-grey-100", children: "Translation providers folder" }), _jsx("div", { className: "mt-0.5 truncate font-mono text-xs text-neutral-grey-50", children: structureSettings.translationProvidersPath })] }), providersFolderExists &&
|
|
253
|
+
structureState?.translationProvidersFolder?.itemId && (_jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleOpenStructureConfig(structureState.translationProvidersFolder.itemId, "Configure: Translation Providers folder"), title: "Configure", children: _jsx(SettingsIcon, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) }))] })] }) }), _jsxs(Card, { icon: _jsx(LanguagesIcon, { strokeWidth: 1, className: "h-5 w-5" }), title: _jsxs(_Fragment, { children: ["Translation providers", " ", _jsxs("span", { className: "font-normal text-neutral-grey-50", children: ["(", configuredCount, " of ", totalCount, " configured)"] })] }), description: "Translation services registered in Parhelia and their settings.", noPadding: true, className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: [((totalCount === 0 && state === "success") || error) && (_jsxs("div", { className: "border-border-default space-y-2 border-t px-4 py-3", children: [totalCount === 0 && state === "success" && (_jsx("div", { className: "rounded border border-feedback-orange bg-feedback-orange-light p-2 text-xs text-feedback-orange", children: "No translation services are registered in dependency injection. Please check the server configuration." })), error && (_jsx("div", { className: "rounded border border-feedback-red bg-feedback-red-light p-2 text-xs whitespace-pre-wrap text-feedback-red", children: error }))] })), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto border-t border-border-default", "data-testid": "translation-services-providers", children: services.length > 0 && (_jsx("div", { className: "divide-y divide-border-default", children: services.map((service) => {
|
|
270
254
|
const isSelected = selectedConfigTarget?.key ===
|
|
271
255
|
`service:${service.serviceName}`;
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
service.
|
|
277
|
-
|
|
278
|
-
|
|
256
|
+
const isConfigured = service.isConfigured;
|
|
257
|
+
return (_jsxs("div", { className: `group flex items-center gap-3 px-3 py-3 text-sm transition-colors ${isSelected
|
|
258
|
+
? "bg-feedback-blue-light"
|
|
259
|
+
: "bg-white hover:bg-neutral-grey-5"}`, children: [isConfigured ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1.5 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx("span", { className: "truncate font-medium text-neutral-grey-100", children: service.displayName || service.serviceName }), service.displayName &&
|
|
260
|
+
service.displayName !== service.serviceName && (_jsx("span", { className: "shrink-0 rounded bg-neutral-grey-5 badge-pad-sm text-[10px] font-medium text-neutral-grey-50", children: service.serviceName })), !isConfigured && (_jsx("span", { className: "shrink-0 rounded bg-feedback-orange-light badge-pad-sm text-[10px] font-medium text-feedback-orange", children: "Not configured" }))] }), isConfigured &&
|
|
261
|
+
service.supportedLanguages &&
|
|
262
|
+
service.supportedLanguages.length > 0 && (_jsxs("div", { className: "mt-0.5 truncate text-xs text-neutral-grey-50", children: ["Languages: ", service.supportedLanguages.join(", ")] }))] }), _jsx("div", { className: "flex shrink-0 items-center gap-0.5", children: isConfigured && service.settingsItemId ? (_jsxs("div", { className: "flex items-center gap-0.5 opacity-60 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleOpenConfig(service), disabled: service.deleting, title: "Configure", children: _jsx(SettingsIcon, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => deleteSettings(service), className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-50", disabled: service.deleting, title: `Delete settings for ${service.displayName || service.serviceName}`, children: service.deleting ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(DeleteIcon, { size: "md" })) })] })) : (_jsxs(Button, { size: "sm", variant: "default", onClick: () => createSettings(service.serviceName, service.templateId), disabled: service.creating, title: `Create settings using template: ${service.templateName}`, children: [service.creating ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "mr-1 h-3.5 w-3.5 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1.75, className: "mr-1 h-3.5 w-3.5" })), "Create"] })) })] }, service.serviceName));
|
|
263
|
+
}) })) })] })] }));
|
|
279
264
|
// Build splitter panels - only show config panel when a service is selected
|
|
280
265
|
const panels = selectedConfigTarget?.itemId
|
|
281
266
|
? [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalizationSetupStep.d.ts","sourceRoot":"","sources":["../../src/setup/LocalizationSetupStep.tsx"],"names":[],"mappings":"AAgCA,wBAAgB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"LocalizationSetupStep.d.ts","sourceRoot":"","sources":["../../src/setup/LocalizationSetupStep.tsx"],"names":[],"mappings":"AAgCA,wBAAgB,qBAAqB,4CA6QpC;AAED,eAAe,qBAAqB,CAAC"}
|
|
@@ -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-[var(--color-feedback-green)]", strokeWidth: 1 }));
|
|
19
19
|
if (state === "error")
|
|
20
|
-
return _jsx(AlertCircleIcon, { className: "h-4 w-4 text-destructive", strokeWidth: 1 });
|
|
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-[var(--color-feedback-orange)]", strokeWidth: 1 }));
|
|
23
|
+
return (_jsx(RefreshCwIcon, { className: "h-4 w-4 animate-spin text-[var(--color-highlight-100)]", strokeWidth: 1 }));
|
|
24
24
|
}, []);
|
|
25
25
|
const checkLocalization = useCallback(async () => {
|
|
26
26
|
try {
|
|
@@ -42,14 +42,14 @@ export function LocalizationSetupStep() {
|
|
|
42
42
|
else {
|
|
43
43
|
const serviceStates = availableServices.map((svc) => ({
|
|
44
44
|
...svc,
|
|
45
|
-
creating: false
|
|
45
|
+
creating: false,
|
|
46
46
|
}));
|
|
47
47
|
setServices(serviceStates);
|
|
48
|
-
const configuredCount = serviceStates.filter(s => s.isConfigured).length;
|
|
48
|
+
const configuredCount = serviceStates.filter((s) => s.isConfigured).length;
|
|
49
49
|
const totalCount = serviceStates.length;
|
|
50
50
|
if (configuredCount === 0) {
|
|
51
51
|
setState("error");
|
|
52
|
-
setError(`Found ${totalCount} translation service${totalCount !== 1 ?
|
|
52
|
+
setError(`Found ${totalCount} translation service${totalCount !== 1 ? "s" : ""} in DI, but none have Sitecore Settings items configured.`);
|
|
53
53
|
}
|
|
54
54
|
else if (configuredCount < totalCount) {
|
|
55
55
|
setState("partial");
|
|
@@ -62,7 +62,8 @@ export function LocalizationSetupStep() {
|
|
|
62
62
|
}
|
|
63
63
|
else {
|
|
64
64
|
setState("error");
|
|
65
|
-
setError(result.details ||
|
|
65
|
+
setError(result.details ||
|
|
66
|
+
"Failed to check translation services. The translation API may not be available.");
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
catch (e) {
|
|
@@ -72,7 +73,7 @@ export function LocalizationSetupStep() {
|
|
|
72
73
|
}, []);
|
|
73
74
|
const createSettings = useCallback(async (serviceName, templateId) => {
|
|
74
75
|
try {
|
|
75
|
-
setServices(prev => prev.map(s => s.serviceName === serviceName ? { ...s, creating: true } : s));
|
|
76
|
+
setServices((prev) => prev.map((s) => s.serviceName === serviceName ? { ...s, creating: true } : s));
|
|
76
77
|
setError(null);
|
|
77
78
|
const language = editContext?.item?.language ??
|
|
78
79
|
editContext?.currentItemDescriptor?.language ??
|
|
@@ -80,13 +81,20 @@ export function LocalizationSetupStep() {
|
|
|
80
81
|
const result = await createProviderSettings(serviceName, templateId, language);
|
|
81
82
|
if (result.type === "success" && result.data) {
|
|
82
83
|
if (result.data.success && result.data.data) {
|
|
83
|
-
setServices(prev => prev.map(s => s.serviceName === serviceName
|
|
84
|
-
? {
|
|
84
|
+
setServices((prev) => prev.map((s) => s.serviceName === serviceName
|
|
85
|
+
? {
|
|
86
|
+
...s,
|
|
87
|
+
isConfigured: true,
|
|
88
|
+
creating: false,
|
|
89
|
+
settingsItemId: result.data?.data?.itemId,
|
|
90
|
+
}
|
|
85
91
|
: s));
|
|
86
92
|
setTimeout(() => checkLocalization(), 500);
|
|
87
93
|
}
|
|
88
94
|
else {
|
|
89
|
-
throw new Error(result.data.error ||
|
|
95
|
+
throw new Error(result.data.error ||
|
|
96
|
+
result.details ||
|
|
97
|
+
"Failed to create settings");
|
|
90
98
|
}
|
|
91
99
|
}
|
|
92
100
|
else {
|
|
@@ -95,22 +103,25 @@ export function LocalizationSetupStep() {
|
|
|
95
103
|
}
|
|
96
104
|
catch (e) {
|
|
97
105
|
setError(`Failed to create settings for ${serviceName}: ${e?.message || "Unknown error"}`);
|
|
98
|
-
setServices(prev => prev.map(s => s.serviceName === serviceName ? { ...s, creating: false } : s));
|
|
106
|
+
setServices((prev) => prev.map((s) => s.serviceName === serviceName ? { ...s, creating: false } : s));
|
|
99
107
|
}
|
|
100
108
|
}, [editContext, checkLocalization]);
|
|
101
109
|
React.useEffect(() => {
|
|
102
110
|
checkLocalization();
|
|
103
111
|
}, [checkLocalization]);
|
|
104
|
-
const configuredCount = services.filter(s => s.isConfigured).length;
|
|
112
|
+
const configuredCount = services.filter((s) => s.isConfigured).length;
|
|
105
113
|
const totalCount = services.length;
|
|
106
|
-
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-
|
|
107
|
-
? `All ${totalCount} translation service${totalCount !== 1 ?
|
|
114
|
+
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-neutral-grey-100", children: state === "success"
|
|
115
|
+
? `All ${totalCount} translation service${totalCount !== 1 ? "s" : ""} configured`
|
|
108
116
|
: state === "partial"
|
|
109
117
|
? `${configuredCount} of ${totalCount} services configured`
|
|
110
118
|
: state === "error" && totalCount > 0
|
|
111
|
-
? `${totalCount} service${totalCount !== 1 ?
|
|
119
|
+
? `${totalCount} service${totalCount !== 1 ? "s" : ""} found, none configured`
|
|
112
120
|
: state === "error"
|
|
113
121
|
? "No services found"
|
|
114
|
-
: "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-
|
|
122
|
+
: "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-border-default bg-neutral-grey-5 p-3", children: [_jsx("div", { className: "text-xs font-medium text-neutral-grey-50 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-border-default", children: [_jsxs("div", { className: "flex items-center gap-2", children: [service.isConfigured ? (_jsx(CheckCircleIcon, { className: "h-3.5 w-3.5 text-[var(--color-feedback-green)]", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-3.5 w-3.5 text-[var(--color-feedback-orange)]", strokeWidth: 1.5 })), _jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-neutral-grey-100", children: service.displayName || service.serviceName }), service.displayName &&
|
|
123
|
+
service.displayName !== service.serviceName && (_jsxs("div", { className: "text-xs text-neutral-grey-50", children: ["Service: ", service.serviceName] })), service.isConfigured &&
|
|
124
|
+
service.supportedLanguages &&
|
|
125
|
+
service.supportedLanguages.length > 0 && (_jsxs("div", { className: "text-xs text-neutral-grey-50", 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-feedback-orange/30 bg-feedback-orange/10 p-3 text-xs whitespace-pre-wrap text-neutral-grey-100", children: error }))] }) }));
|
|
115
126
|
}
|
|
116
127
|
export default LocalizationSetupStep;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TranslationSidebar.d.ts","sourceRoot":"","sources":["../../src/sidebar/TranslationSidebar.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TranslationSidebar.d.ts","sourceRoot":"","sources":["../../src/sidebar/TranslationSidebar.tsx"],"names":[],"mappings":"AAkBA,wBAAgB,kBAAkB,mDA8NjC"}
|
|
@@ -3,6 +3,9 @@ import { Button, useEditContext, SimpleTable, confirmCreateVersion, Progress, }
|
|
|
3
3
|
import { getTranslationStatus } from "../services/translationService";
|
|
4
4
|
import { useEffect, useState } from "react";
|
|
5
5
|
import { localizeItemCommand } from "../LocalizeItemCommand";
|
|
6
|
+
function isActiveTranslationStatus(status) {
|
|
7
|
+
return status === "Pending" || status === "In Progress";
|
|
8
|
+
}
|
|
6
9
|
export function TranslationSidebar() {
|
|
7
10
|
const editContext = useEditContext();
|
|
8
11
|
if (!editContext)
|
|
@@ -25,7 +28,7 @@ export function TranslationSidebar() {
|
|
|
25
28
|
});
|
|
26
29
|
};
|
|
27
30
|
const languageName = (language) => {
|
|
28
|
-
return (_jsxs("div", { className: "flex items-center gap-2 text-
|
|
31
|
+
return (_jsxs("div", { className: "flex items-center gap-2 text-neutral-grey-100", 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
32
|
};
|
|
30
33
|
const loadTranslationStatus = async () => {
|
|
31
34
|
if (!item)
|
|
@@ -72,7 +75,11 @@ export function TranslationSidebar() {
|
|
|
72
75
|
const effectiveStatus = progress ? "In Progress" : status?.status;
|
|
73
76
|
return {
|
|
74
77
|
...x,
|
|
75
|
-
translationStatus: status
|
|
78
|
+
translationStatus: status
|
|
79
|
+
? { ...status, status: effectiveStatus }
|
|
80
|
+
: progress
|
|
81
|
+
? { status: "In Progress" }
|
|
82
|
+
: undefined,
|
|
76
83
|
translationProgress: progress,
|
|
77
84
|
};
|
|
78
85
|
});
|
|
@@ -85,7 +92,7 @@ export function TranslationSidebar() {
|
|
|
85
92
|
// Sort by name for languages that both have versions or both don't
|
|
86
93
|
return a.name.localeCompare(b.name);
|
|
87
94
|
});
|
|
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-
|
|
95
|
+
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-border-default p-1 px-2", children: item && (_jsx(Button, { size: "xs", "data-testid": "translation-sidebar-localize-button", onClick: () => {
|
|
89
96
|
editContext.executeCommand({
|
|
90
97
|
command: localizeItemCommand,
|
|
91
98
|
data: {
|
|
@@ -94,20 +101,23 @@ export function TranslationSidebar() {
|
|
|
94
101
|
});
|
|
95
102
|
}, children: "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: [
|
|
96
103
|
{ header: "Language", body: languageName },
|
|
97
|
-
{
|
|
104
|
+
{
|
|
105
|
+
header: "Ver.",
|
|
106
|
+
body: (x) => (_jsx("span", { className: "text-neutral-grey-100", children: x.versions.toString() })),
|
|
107
|
+
},
|
|
98
108
|
{
|
|
99
109
|
header: "Src",
|
|
100
|
-
body: (x) => _jsx("span", { className: "text-
|
|
110
|
+
body: (x) => (_jsx("span", { className: "text-neutral-grey-50", children: x.translationStatus?.sourceLanguage })),
|
|
101
111
|
},
|
|
102
112
|
{
|
|
103
113
|
header: "Status",
|
|
104
|
-
body: (x) => (_jsxs("div", { className: "flex items-center gap-2", "data-testid": `translation-status-${x.languageCode}`, children: [x.translationStatus?.status
|
|
105
|
-
? "text-green
|
|
114
|
+
body: (x) => (_jsxs("div", { className: "flex items-center gap-2", "data-testid": `translation-status-${x.languageCode}`, children: [isActiveTranslationStatus(x.translationStatus?.status) && (_jsxs("div", { className: "relative w-full", children: [_jsx(Progress, { className: "h-5", value: (x.translationProgress?.progress || 0) * 100, showValue: false, indicatorClassName: "bg-[var(--color-highlight-100)]", "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 })] })), !isActiveTranslationStatus(x.translationStatus?.status) && (_jsx("span", { title: x.translationStatus?.message, className: x.translationStatus?.status === "Completed"
|
|
115
|
+
? "text-feedback-green font-medium"
|
|
106
116
|
: x.translationStatus?.status === "Error"
|
|
107
|
-
? "text-red
|
|
108
|
-
: "text-
|
|
117
|
+
? "text-feedback-red font-medium"
|
|
118
|
+
: "text-neutral-grey-50", children: x.translationStatus?.status || "Not started" }))] })),
|
|
109
119
|
},
|
|
110
120
|
], items: languageData, onRowClick: (data) => selectLanguage(data.item), rowClassName: (item) => item.languageCode == editContext.currentItemDescriptor?.language
|
|
111
|
-
? "bg-[
|
|
121
|
+
? "bg-[var(--color-highlight-10)]"
|
|
112
122
|
: "" }) }) })] }));
|
|
113
123
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ItemSelectionStep.d.ts","sourceRoot":"","sources":["../../src/steps/ItemSelectionStep.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAI/C,wBAAgB,iBAAiB,CAAC,EAChC,QAAe,EACf,IAAI,EACJ,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE,oBAAoB,2CAoCtB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { ItemSelectionTree } from "./ItemSelectionTree";
|
|
4
|
+
import { WizardStepShell } from "./WizardStepShell";
|
|
5
|
+
export function ItemSelectionStep({ isActive = true, data, setData, onStepCompleted, editContext, }) {
|
|
6
|
+
const multiItemEnabled = editContext?.configuration?.localization?.multiItem !== false;
|
|
7
|
+
const [itemSelectionValid, setItemSelectionValid] = useState(!multiItemEnabled ||
|
|
8
|
+
(data.selectionTreeItems?.length ?? data.items.length) > 0);
|
|
9
|
+
const onStepCompletedRef = useRef(onStepCompleted);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
onStepCompletedRef.current = onStepCompleted;
|
|
12
|
+
}, [onStepCompleted]);
|
|
13
|
+
const lastCompletionRef = useRef(null);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (!isActive)
|
|
16
|
+
return;
|
|
17
|
+
const completed = !multiItemEnabled || itemSelectionValid;
|
|
18
|
+
if (lastCompletionRef.current !== completed) {
|
|
19
|
+
lastCompletionRef.current = completed;
|
|
20
|
+
onStepCompletedRef.current(completed);
|
|
21
|
+
}
|
|
22
|
+
}, [isActive, itemSelectionValid, multiItemEnabled]);
|
|
23
|
+
return (_jsx(WizardStepShell, { fillHeight: true, testId: "item-selection-step", children: _jsx(ItemSelectionTree, { data: data, setData: setData, editContext: editContext, isActive: isActive, onSelectionValidChange: setItemSelectionValid, height: "100%" }) }));
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type EditContextType } from "@parhelia/core";
|
|
2
|
+
import type { TranslationWizardData } from "./types";
|
|
3
|
+
type ItemSelectionTreeProps = {
|
|
4
|
+
data: TranslationWizardData;
|
|
5
|
+
setData: (data: TranslationWizardData) => void;
|
|
6
|
+
editContext: EditContextType;
|
|
7
|
+
isActive?: boolean;
|
|
8
|
+
onSelectionValidChange?: (valid: boolean) => void;
|
|
9
|
+
height?: number | string;
|
|
10
|
+
};
|
|
11
|
+
export declare function ItemSelectionTree({ data, setData, editContext, isActive, onSelectionValidChange, height, }: ItemSelectionTreeProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=ItemSelectionTree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ItemSelectionTree.d.ts","sourceRoot":"","sources":["../../src/steps/ItemSelectionTree.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,eAAe,EAMrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAGrD,KAAK,sBAAsB,GAAG;IAC5B,IAAI,EAAE,qBAAqB,CAAC;IAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC/C,WAAW,EAAE,eAAe,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B,CAAC;AAkEF,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,OAAO,EACP,WAAW,EACX,QAAe,EACf,sBAAsB,EACtB,MAAY,GACb,EAAE,sBAAsB,2CA4VxB"}
|