@parhelia/localization 0.2.12764 → 0.2.12768
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/LocalizeItemDialog.js +2 -2
- package/dist/settings/TranslationServicesPanel.js +7 -7
- package/dist/setup/LocalizationSetupStep.js +2 -2
- package/dist/steps/ProviderStep.d.ts.map +1 -1
- package/dist/steps/ProviderStep.js +2 -2
- package/dist/translation-center/TranslationBatches.d.ts.map +1 -1
- package/dist/translation-center/TranslationBatches.js +10 -10
- package/package.json +1 -1
|
@@ -290,7 +290,7 @@ export function LocalizeItemDialog(props) {
|
|
|
290
290
|
}, children: [_jsxs(DialogContent, { className: "flex max-h-[900px] min-h-0 max-w-5xl flex-col overflow-visible md:min-h-[700px]", "data-testid": "translation-wizard-dialog", onPointerDownOutside: (e) => e.preventDefault(), onEscapeKeyDown: (e) => e.preventDefault(), "aria-describedby": "translation-wizard-description", style: {
|
|
291
291
|
width: isMobile ? "calc(100vw - 24px)" : "min(90vw, 1280px)",
|
|
292
292
|
height: isMobile ? "min(92dvh, 900px)" : "min(85vh, 900px)",
|
|
293
|
-
}, children: [_jsxs("div", { className: "flex h-full min-h-0 w-full flex-col overflow-hidden rounded-2xl bg-white", children: [_jsx(StyledDialogTitle, { icon: _jsx(GlobeIcon, { strokeWidth: 1
|
|
293
|
+
}, children: [_jsxs("div", { className: "flex h-full min-h-0 w-full flex-col overflow-hidden rounded-2xl bg-white", children: [_jsx(StyledDialogTitle, { icon: _jsx(GlobeIcon, { strokeWidth: 1 }), title: `Translate · ${currentStep?.name ?? ""}`, subtitle: currentStep?.description ||
|
|
294
294
|
"Configure and start translation for your content" }), _jsx("div", { id: "translation-wizard-description", className: "sr-only", children: currentStep?.description ||
|
|
295
295
|
"Configure and start translation for your content." }), _jsxs("div", { className: "flex flex-1 flex-col min-h-0", children: [_jsx("div", { className: "flex-1 overflow-y-auto min-h-0 ", "data-testid": "translation-wizard-step-content", children: _jsx("div", { className: "h-full relative", children: activeSteps.map((step, index) => {
|
|
296
296
|
const StepComponent = step.component;
|
|
@@ -303,7 +303,7 @@ export function LocalizeItemDialog(props) {
|
|
|
303
303
|
if (totalTranslations <= 0)
|
|
304
304
|
return "Start Translation";
|
|
305
305
|
return `Start Translation (${totalTranslations}${isStreaming ? "+" : ""})`;
|
|
306
|
-
})()) : (_jsxs(_Fragment, { children: [getNextButtonLabel(activeSteps[currentStepIndex + 1]), _jsx(ArrowRightIcon, { className: "h-4 w-4", strokeWidth:
|
|
306
|
+
})()) : (_jsxs(_Fragment, { children: [getNextButtonLabel(activeSteps[currentStepIndex + 1]), _jsx(ArrowRightIcon, { className: "h-4 w-4", strokeWidth: 1 })] })) })] })] })] })] }), _jsx(StepIndicatorDots, { steps: activeSteps, currentStepIndex: currentStepIndex })] }), _jsx(AlertDialog, { open: showLargeBatchWarning, onOpenChange: setShowLargeBatchWarning, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsxs(AlertDialogTitle, { className: "flex items-center gap-2", children: [_jsx(AlertTriangleIcon, { className: "h-5 w-5 text-feedback-orange" }), "Large Translation Batch"] }), _jsx(AlertDialogDescription, { children: (() => {
|
|
307
307
|
const { itemCount, languageCount, totalTranslations } = calculateTranslationCounts(wizardData);
|
|
308
308
|
return (_jsxs(_Fragment, { children: ["You are about to start", " ", _jsxs("strong", { children: [totalTranslations, " translations"] }), " (", itemCount, " items \u00D7 ", languageCount, " languages). Large batches may take a significant amount of time to process.", _jsx("br", {}), _jsx("br", {}), "Are you sure you want to continue?"] }));
|
|
309
309
|
})() })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isSubmitting, children: "Cancel" }), _jsx(AlertDialogAction, { onClick: handleLargeBatchConfirm, disabled: isSubmitting, children: isSubmitting ? "Starting..." : "Continue" })] })] }) })] }));
|
|
@@ -242,24 +242,24 @@ export function TranslationServicesPanel() {
|
|
|
242
242
|
const translationFolderExists = !!structureState?.translationFolder?.exists;
|
|
243
243
|
const providersFolderExists = !!structureState?.translationProvidersFolder?.exists;
|
|
244
244
|
// Build the services list content
|
|
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
|
|
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 }), "All parent items found"] })) : (_jsxs(_Fragment, { children: [_jsx(AlertCircleIcon, { className: "h-3.5 w-3.5 text-feedback-orange", strokeWidth: 1 }), "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, 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
246
|
`structure:${structureState?.translationFolder?.itemId}`
|
|
247
247
|
? "bg-feedback-blue-light"
|
|
248
|
-
: "bg-white"}`, children: [translationFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1
|
|
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
|
|
248
|
+
: "bg-white"}`, children: [translationFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1 })), _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 }) }))] }), _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
250
|
`structure:${structureState?.translationProvidersFolder?.itemId}`
|
|
251
251
|
? "bg-feedback-blue-light"
|
|
252
|
-
: "bg-white"}`, children: [providersFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1
|
|
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
|
|
252
|
+
: "bg-white"}`, children: [providersFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1 })), _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 }) }))] })] }) }), _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) => {
|
|
254
254
|
const isSelected = selectedConfigTarget?.key ===
|
|
255
255
|
`service:${service.serviceName}`;
|
|
256
256
|
const isConfigured = service.isConfigured;
|
|
257
257
|
return (_jsxs("div", { className: `group flex items-center gap-3 px-3 py-3 text-sm transition-colors ${isSelected
|
|
258
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
|
|
259
|
+
: "bg-white hover:bg-neutral-grey-5"}`, children: [isConfigured ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1 })), _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
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
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
|
|
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 }) }), _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, className: "mr-1 h-3.5 w-3.5" })), "Create"] })) })] }, service.serviceName));
|
|
263
263
|
}) })) })] })] }));
|
|
264
264
|
// Build splitter panels - only show config panel when a service is selected
|
|
265
265
|
const panels = selectedConfigTarget?.itemId
|
|
@@ -119,9 +119,9 @@ export function LocalizationSetupStep() {
|
|
|
119
119
|
? `${totalCount} service${totalCount !== 1 ? "s" : ""} found, none configured`
|
|
120
120
|
: state === "error"
|
|
121
121
|
? "No services found"
|
|
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
|
|
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 })) : (_jsx(AlertCircleIcon, { className: "h-3.5 w-3.5 text-[var(--color-feedback-orange)]", strokeWidth: 1 })), _jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-neutral-grey-100", children: service.displayName || service.serviceName }), service.displayName &&
|
|
123
123
|
service.displayName !== service.serviceName && (_jsxs("div", { className: "text-xs text-neutral-grey-50", children: ["Service: ", service.serviceName] })), service.isConfigured &&
|
|
124
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
|
|
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, 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 }))] }) }));
|
|
126
126
|
}
|
|
127
127
|
export default LocalizationSetupStep;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderStep.d.ts","sourceRoot":"","sources":["../../src/steps/ProviderStep.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ProviderStep.d.ts","sourceRoot":"","sources":["../../src/steps/ProviderStep.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAUf,OAAO,EAAE,oBAAoB,EAAyB,MAAM,SAAS,CAAC;AAQtE,wBAAgB,YAAY,CAAC,EAC3B,QAAe,EACf,IAAI,EACJ,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE,oBAAoB,qBAqXtB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState, } from "react";
|
|
3
3
|
import { Button, Input, Label, Select, Spinner, Textarea, } from "@parhelia/core";
|
|
4
4
|
import { RotateCcw } from "lucide-react";
|
|
5
5
|
import { WizardStepShell } from "./WizardStepShell";
|
|
@@ -219,5 +219,5 @@ export function ProviderStep({ isActive = true, data, setData, onStepCompleted,
|
|
|
219
219
|
}), options: data.translationProviders.map((provider) => ({
|
|
220
220
|
value: provider.name,
|
|
221
221
|
label: provider.displayName || provider.name,
|
|
222
|
-
})), placeholder: "Select a provider...", size: "sm", className: "mt-2 w-full", "data-testid": "translation-provider-select" }), isCreateLanguageVersionsOnlyProvider && (_jsx("p", { className: "text-muted-foreground mt-2 text-xs", children: "\"Create Language Versions Only\" will create new language versions without automatic translation." }))] }), supportsPromptCustomization && (_jsxs("div", { children: [_jsxs(Label, { className: "flex cursor-pointer items-start gap-2.5", children: [_jsx("input", { type: "checkbox", checked: enableCustomPrompt, onChange: (e) => handleCustomPromptToggle(e.target.checked), className: "mt-0.5 h-3.5 w-3.5 rounded border-border-default text-[var(--color-highlight-100)] accent-[var(--color-highlight-100)] focus:ring-[var(--color-highlight-100)]", "data-testid": "enable-custom-prompt-checkbox" }), _jsxs("div", { className: "min-w-0", children: [_jsx("span", { className: "block text-[13px] font-medium text-neutral-grey-100", children: "Customize translation prompt (optional)" }), _jsx("span", { className: "text-muted-foreground mt-0.5 block text-xs", children: "Edit the provider prompt before starting translation." })] })] }), enableCustomPrompt && (_jsxs("div", { className: "mt-4 space-y-2", children: [_jsx(Textarea, { id: "custom-prompt-textarea", value: customPrompt, onChange: (e) => setCustomPrompt(e.target.value), className: "text-xs", rows: 8, placeholder: "Enter prompt instructions here...", "data-testid": "custom-prompt-textarea" }), hasDefaultPrompt && (_jsxs(Button, { type: "button", size: "sm", variant: "outline", onClick: handleResetPrompt, disabled: customPrompt === (defaultPrompt || ""), className: "gap-1.5", title: "Reset to the default prompt", "data-testid": "reset-custom-prompt-button", children: [_jsx(ResetIcon, { className: "size-3.5", strokeWidth: 1
|
|
222
|
+
})), placeholder: "Select a provider...", size: "sm", className: "mt-2 w-full", "data-testid": "translation-provider-select" }), isCreateLanguageVersionsOnlyProvider && (_jsx("p", { className: "text-muted-foreground mt-2 text-xs", children: "\"Create Language Versions Only\" will create new language versions without automatic translation." }))] }), supportsPromptCustomization && (_jsxs("div", { children: [_jsxs(Label, { className: "flex cursor-pointer items-start gap-2.5", children: [_jsx("input", { type: "checkbox", checked: enableCustomPrompt, onChange: (e) => handleCustomPromptToggle(e.target.checked), className: "mt-0.5 h-3.5 w-3.5 rounded border-border-default text-[var(--color-highlight-100)] accent-[var(--color-highlight-100)] focus:ring-[var(--color-highlight-100)]", "data-testid": "enable-custom-prompt-checkbox" }), _jsxs("div", { className: "min-w-0", children: [_jsx("span", { className: "block text-[13px] font-medium text-neutral-grey-100", children: "Customize translation prompt (optional)" }), _jsx("span", { className: "text-muted-foreground mt-0.5 block text-xs", children: "Edit the provider prompt before starting translation." })] })] }), enableCustomPrompt && (_jsxs("div", { className: "mt-4 space-y-2", children: [_jsx(Textarea, { id: "custom-prompt-textarea", value: customPrompt, onChange: (e) => setCustomPrompt(e.target.value), className: "text-xs", rows: 8, placeholder: "Enter prompt instructions here...", "data-testid": "custom-prompt-textarea" }), hasDefaultPrompt && (_jsxs(Button, { type: "button", size: "sm", variant: "outline", onClick: handleResetPrompt, disabled: customPrompt === (defaultPrompt || ""), className: "gap-1.5", title: "Reset to the default prompt", "data-testid": "reset-custom-prompt-button", children: [_jsx(ResetIcon, { className: "size-3.5", strokeWidth: 1, "aria-hidden": "true" }), "Reset to default"] }))] }))] }))] })] }) }) }));
|
|
223
223
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TranslationBatches.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationBatches.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAgV1B,wBAAgB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"TranslationBatches.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationBatches.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAgV1B,wBAAgB,kBAAkB,sBA+mCjC;AAED,eAAO,MAAM,oCAAoC,8BAA8B,CAAC;AAEhF,wBAAgB,8BAA8B,sBA0Y7C"}
|
|
@@ -35,7 +35,7 @@ function renderTargetLanguageIcon(language) {
|
|
|
35
35
|
}
|
|
36
36
|
return React.createElement(GlobeIcon, {
|
|
37
37
|
className: "h-3.5 w-3.5 text-neutral-grey-50",
|
|
38
|
-
strokeWidth: 1
|
|
38
|
+
strokeWidth: 1,
|
|
39
39
|
"aria-hidden": true,
|
|
40
40
|
});
|
|
41
41
|
}
|
|
@@ -854,7 +854,7 @@ export function TranslationBatches() {
|
|
|
854
854
|
if (!canRetry)
|
|
855
855
|
return;
|
|
856
856
|
void handleRetryBatch(info);
|
|
857
|
-
}, icon: _jsx(RetryIcon, { className: `h-3.5 w-3.5 ${isRetryingBatch ? "animate-spin" : ""}`, strokeWidth: 1
|
|
857
|
+
}, icon: _jsx(RetryIcon, { className: `h-3.5 w-3.5 ${isRetryingBatch ? "animate-spin" : ""}`, strokeWidth: 1 }), label: "Retry failed translations", disabled: !canRetry ||
|
|
858
858
|
isRetryingBatch ||
|
|
859
859
|
isLoadingThis ||
|
|
860
860
|
isAborting })), canAbort && (_jsx(SimpleIconButton, { onClick: (event) => {
|
|
@@ -862,7 +862,7 @@ export function TranslationBatches() {
|
|
|
862
862
|
if (!canAbort)
|
|
863
863
|
return;
|
|
864
864
|
handleAbortBatch(b.id);
|
|
865
|
-
}, icon: _jsx(AbortIcon, { className: `h-3.5 w-3.5 ${isAborting ? "animate-spin" : ""}`, strokeWidth: 1
|
|
865
|
+
}, icon: _jsx(AbortIcon, { className: `h-3.5 w-3.5 ${isAborting ? "animate-spin" : ""}`, strokeWidth: 1 }), label: "Abort translation batch", disabled: !canAbort || isAborting }))] }));
|
|
866
866
|
return (_jsxs("div", { "data-testid": `batch-row-${b.id}`, "data-batch-status": testStatus, children: [_jsx("div", { role: "button", tabIndex: 0, className: `group w-full cursor-pointer py-3 text-left transition-colors hover:bg-neutral-grey-5 ${isCompactBatches ? "px-2.5" : "px-4"}`, onClick: () => toggleBatch(b.id), onKeyDown: (e) => {
|
|
867
867
|
if (e.key === "Enter" || e.key === " ") {
|
|
868
868
|
e.preventDefault();
|
|
@@ -969,7 +969,7 @@ export function TranslationBatchFiltersSidebar() {
|
|
|
969
969
|
const filterFieldClass = "flex flex-col gap-1";
|
|
970
970
|
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col bg-white", "data-testid": "translation-filters-sidebar", children: [_jsx("div", { className: "border-border-default flex shrink-0 flex-col gap-2 border-b px-3 py-3", children: _jsxs(Button, { type: "button", variant: "outline", size: "lg", title: canStartTranslation
|
|
971
971
|
? "Start new translation"
|
|
972
|
-
: "Open an item to translate", "data-testid": "translation-sidebar-start-new-translation-button", disabled: !canStartTranslation, onClick: handleStartTranslation, className: "border-border-default hover:border-neutral-grey-100 hover:bg-neutral-grey-5 h-9 w-full justify-center gap-3 rounded-md bg-white px-3 text-sm font-medium shadow-none", children: [_jsx("span", { className: "truncate", children: "Start new translation" }), _jsx(PlusIcon, { className: "size-4", strokeWidth: 1
|
|
972
|
+
: "Open an item to translate", "data-testid": "translation-sidebar-start-new-translation-button", disabled: !canStartTranslation, onClick: handleStartTranslation, className: "border-border-default hover:border-neutral-grey-100 hover:bg-neutral-grey-5 h-9 w-full justify-center gap-3 rounded-md bg-white px-3 text-sm font-medium shadow-none", children: [_jsx("span", { className: "truncate", children: "Start new translation" }), _jsx(PlusIcon, { className: "size-4", strokeWidth: 1 })] }) }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 py-4", children: _jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: filterFieldClass, children: [_jsx("label", { className: filterLabelClass, children: "Date Range" }), _jsx(Select, { className: "w-full bg-white", options: DATE_RANGE_OPTIONS, value: filters.dateRange, onValueChange: (value) => setTranslationBatchFilters((prev) => ({
|
|
973
973
|
...prev,
|
|
974
974
|
dateRange: value,
|
|
975
975
|
})), placeholder: "Select date range" })] }), _jsxs("div", { className: filterFieldClass, children: [_jsx("label", { className: filterLabelClass, children: "Status" }), _jsx(Select, { className: "w-full bg-white", options: STATUS_OPTIONS, value: filters.status, onValueChange: (value) => setTranslationBatchFilters((prev) => ({
|
|
@@ -1173,7 +1173,7 @@ function BatchProgressIndicator({ value, completedJobs, totalJobs, errorJobs, to
|
|
|
1173
1173
|
backgroundColor: toneColor,
|
|
1174
1174
|
} }) }), _jsxs("span", { className: `shrink-0 text-[11px] leading-none font-medium tabular-nums ${toneClass}`, children: [percent, "%"] })] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: label })] }));
|
|
1175
1175
|
}
|
|
1176
|
-
return (_jsxs(Tooltip, { delayDuration: 250, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: `relative h-10 w-10 shrink-0 rounded-full ${tone === "complete" ? "bg-feedback-green-light" : ""}`, "aria-label": label, "data-testid": testId, children: [_jsxs("svg", { className: "h-10 w-10 -rotate-90", viewBox: "0 0 40 40", children: [_jsx("circle", { cx: "20", cy: "20", r: radius, fill: "none", stroke: trackColor, strokeWidth:
|
|
1176
|
+
return (_jsxs(Tooltip, { delayDuration: 250, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: `relative h-10 w-10 shrink-0 rounded-full ${tone === "complete" ? "bg-feedback-green-light" : ""}`, "aria-label": label, "data-testid": testId, children: [_jsxs("svg", { className: "h-10 w-10 -rotate-90", viewBox: "0 0 40 40", children: [_jsx("circle", { cx: "20", cy: "20", r: radius, fill: "none", stroke: trackColor, strokeWidth: 1 }), _jsx("circle", { cx: "20", cy: "20", r: radius, fill: "none", stroke: toneColor, strokeLinecap: "round", strokeWidth: 1, style: {
|
|
1177
1177
|
strokeDasharray: circumference,
|
|
1178
1178
|
strokeDashoffset: dashOffset,
|
|
1179
1179
|
} })] }), _jsxs("span", { className: `absolute inset-0 flex items-center justify-center text-[10px] leading-none font-medium tabular-nums ${toneClass}`, children: [percent, "%"] })] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: label })] }));
|
|
@@ -1249,10 +1249,10 @@ function CustomPromptPanel({ prompts }) {
|
|
|
1249
1249
|
e.preventDefault();
|
|
1250
1250
|
setOpenProvider(isOpen ? null : p.provider);
|
|
1251
1251
|
}
|
|
1252
|
-
}, children: [_jsx(SparklesIcon, { className: "h-3 w-3 shrink-0 text-highlight-100", strokeWidth: 1
|
|
1252
|
+
}, children: [_jsx(SparklesIcon, { className: "h-3 w-3 shrink-0 text-highlight-100", strokeWidth: 1 }), _jsx("span", { className: "text-neutral-grey-100", children: "Custom prompt" }), _jsx("span", { className: "text-neutral-grey-15", children: "\u00B7" }), _jsx("span", { children: p.provider }), _jsxs("span", { className: "ml-auto flex items-center gap-2", children: [isOpen && (_jsx(SimpleIconButton, { onClick: (event) => {
|
|
1253
1253
|
event.stopPropagation();
|
|
1254
1254
|
void handleCopy(p.provider, p.prompt);
|
|
1255
|
-
}, icon: justCopied ? (_jsx(CheckIcon, { className: "h-3.5 w-3.5", strokeWidth: 1
|
|
1255
|
+
}, icon: justCopied ? (_jsx(CheckIcon, { className: "h-3.5 w-3.5", strokeWidth: 1 })) : (_jsx(CopyIcon, { className: "h-3.5 w-3.5", strokeWidth: 1 })), label: justCopied ? "Copied" : "Copy prompt" })), _jsx(ChevronDownIcon, { className: `h-3.5 w-3.5 text-neutral-grey-100 transition-transform ${isOpen ? "rotate-180" : ""}` })] })] }), isOpen && (_jsx("div", { style: { paddingLeft: "2.5rem" }, className: "pr-3 md:pr-4 pb-3", children: _jsx("pre", { className: "max-h-64 overflow-y-auto whitespace-pre-wrap break-words rounded border border-border-default/50 bg-white p-2 font-mono text-[12px] text-neutral-grey-100", children: p.prompt }) }))] }, p.provider));
|
|
1256
1256
|
}) }));
|
|
1257
1257
|
}
|
|
1258
1258
|
function BatchItemList({ batchId, batchProvider, jobs, isLoading, expandedItems, languages, currentLanguage, itemFilter, itemIncludeSubitems, statusFilter, batchIsTerminal, batchStartedAtUtc, abortingJobIds, retryingKeys, isMobile = false, onToggleItem, onOpenItem, onAbortJob, onRetryJobs, }) {
|
|
@@ -1427,8 +1427,8 @@ function BatchItemList({ batchId, batchProvider, jobs, isLoading, expandedItems,
|
|
|
1427
1427
|
if (itemErrorJobs.length === 0)
|
|
1428
1428
|
return;
|
|
1429
1429
|
void onRetryJobs(batchId, batchProvider, itemErrorJobs, itemRetryKey);
|
|
1430
|
-
}, icon: _jsx(RetryIcon, { className: `h-3.5 w-3.5 ${isRetryingItem ? "animate-spin" : ""}`, strokeWidth: 1
|
|
1431
|
-
const itemContent = (_jsxs("div", { className: `flex min-w-0 items-start ${stackLanguageChips ? "gap-2" : "gap-2.5"}`, children: [_jsx("span", { className: "mt-1 shrink-0", children: itemAnyInProgress ? (_jsx(LoaderIcon, { className: "h-3 w-3 animate-spin text-highlight-100" })) : itemIsQueued ? (_jsx(QueuedIcon, { className: "h-3 w-3 text-neutral-grey-50", strokeWidth: 1
|
|
1430
|
+
}, icon: _jsx(RetryIcon, { className: `h-3.5 w-3.5 ${isRetryingItem ? "animate-spin" : ""}`, strokeWidth: 1 }), label: "Retry failed translations for this item", disabled: itemErrorJobs.length === 0 || isRetryingItem }) })) : null;
|
|
1431
|
+
const itemContent = (_jsxs("div", { className: `flex min-w-0 items-start ${stackLanguageChips ? "gap-2" : "gap-2.5"}`, children: [_jsx("span", { className: "mt-1 shrink-0", children: itemAnyInProgress ? (_jsx(LoaderIcon, { className: "h-3 w-3 animate-spin text-highlight-100" })) : itemIsQueued ? (_jsx(QueuedIcon, { className: "h-3 w-3 text-neutral-grey-50", strokeWidth: 1, "aria-label": "Queued" })) : (_jsx("span", { className: `block h-1.5 w-1.5 rounded-full ${status.cls}`, "aria-hidden": "true" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("span", { className: `block min-w-0 text-[13px] text-neutral-grey-100 ${stackLanguageChips ? "break-words" : "truncate"}`, style: stackLanguageChips
|
|
1432
1432
|
? { overflowWrap: "anywhere" }
|
|
1433
1433
|
: undefined, title: titleAttr, children: displayName }), itemPath && (_jsx("div", { className: "whitespace-normal break-words font-mono text-[11px] text-neutral-grey-50", style: { overflowWrap: "anywhere" }, title: titleAttr, children: itemPath })), stackLanguageChips && (_jsx("div", { className: "mt-2", children: languageChips })), stackLanguageChips && retryAction && (_jsx("div", { className: "mt-2 flex justify-start", children: retryAction }))] })] }));
|
|
1434
1434
|
return (_jsxs("tr", { role: "button", tabIndex: 0, className: `group cursor-pointer transition-colors hover:bg-neutral-grey-5 ${itemIndex > 0 ? "border-t border-border-default/50" : ""}`, onClick: () => {
|
|
@@ -1525,7 +1525,7 @@ function LanguageJobChip({ job, language, batchStartedAtUtc, onOpen, isAborting
|
|
|
1525
1525
|
const emptyFieldText = statistics && statistics.emptyFieldCount > 0
|
|
1526
1526
|
? `${formatCount(statistics.emptyFieldCount)} empty`
|
|
1527
1527
|
: null;
|
|
1528
|
-
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: `group inline-flex items-center gap-1.5 rounded border badge-pad-sm text-[12px] transition-colors cursor-pointer ${chipCls}`, children: [language?.icon ? (_jsx("img", { src: language.icon, alt: langName, className: "h-3.5 shrink-0" })) : null, _jsx("span", { className: "font-mono tracking-tight", children: job.targetLanguage }), jobInProgress && (_jsx(LoaderIcon, { className: "h-3 w-3 shrink-0 animate-spin" })), jobPending && (_jsx(QueuedIcon, { className: "h-3 w-3 shrink-0", strokeWidth: 1
|
|
1528
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: `group inline-flex items-center gap-1.5 rounded border badge-pad-sm text-[12px] transition-colors cursor-pointer ${chipCls}`, children: [language?.icon ? (_jsx("img", { src: language.icon, alt: langName, className: "h-3.5 shrink-0" })) : null, _jsx("span", { className: "font-mono tracking-tight", children: job.targetLanguage }), jobInProgress && (_jsx(LoaderIcon, { className: "h-3 w-3 shrink-0 animate-spin" })), jobPending && (_jsx(QueuedIcon, { className: "h-3 w-3 shrink-0", strokeWidth: 1, "aria-label": "Queued" })), jobError && _jsx(AlertCircleIcon, { className: "h-3 w-3 shrink-0" }), !jobInProgress && !jobError && !jobPending && !jobAborted && (_jsx(CheckIcon, { className: "h-3 w-3 shrink-0 text-feedback-green" }))] }) }), _jsxs(PopoverContent, { align: "start", sideOffset: 6, className: "w-[22rem] max-w-[calc(100vw-2rem)] p-0", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-border-default px-3 py-2", children: [language?.icon ? (_jsx("img", { src: language.icon, alt: langName, className: "h-4 shrink-0" })) : null, _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-[13px] font-medium text-neutral-grey-100 truncate", children: langName }), _jsxs("div", { className: "text-[11px] text-neutral-grey-50 font-mono truncate", children: [job.targetLanguage, job.sourceLanguage ? ` ← ${job.sourceLanguage}` : ""] })] }), _jsxs(Badge, { size: "sm", className: statusBadgeCls, children: [jobInProgress && (_jsx(LoaderIcon, { className: "h-2.5 w-2.5 animate-spin" })), jobStatus || "Unknown"] })] }), _jsxs("dl", { className: "divide-y divide-border-default/60", children: [claimedAtValid && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Claimed" }), _jsx("dd", { className: "text-[12px] text-neutral-grey-100", children: formatDateTime(claimedAt) })] })), timestampValid && (jobInProgress || jobPending) && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Updated" }), _jsx("dd", { className: "text-[12px] text-neutral-grey-100", children: formatDateTime(timestamp) })] })), durationMs != null && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: jobInProgress || jobPending ? "Running" : "Duration" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", title: durationApproximated
|
|
1529
1529
|
? "Approximate — measured from batch start"
|
|
1530
1530
|
: undefined, children: [durationApproximated ? "~" : "", formatDuration(durationMs)] })] })), statistics && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Fields" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: [fieldText, emptyFieldText ? (_jsxs("span", { className: "ml-1.5 text-neutral-grey-50", children: ["(", emptyFieldText, ")"] })) : null] })] })), statistics && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Text" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: [formatCount(statistics.sourceCharacterCount), " chars"] })] })), job.totalCost != null && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Cost" }), _jsx("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: formatUsdCost(job.totalCost) })] })), lastHeartbeatValid && (jobInProgress || jobPending) && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Heartbeat" }), _jsx("dd", { className: "text-[12px] text-neutral-grey-100", children: formatDateTime(lastHeartbeat) })] })), attemptCount > 1 && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Attempts" }), _jsx("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: attemptCount })] })), job.hash && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Hash" }), _jsx("dd", { className: "text-[11px] font-mono text-neutral-grey-100 break-all", children: job.hash })] })), job.message &&
|
|
1531
1531
|
(jobError || jobAborted ? (
|