@parhelia/localization 0.1.12928 → 0.1.12931

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.
@@ -1 +1 @@
1
- {"version":3,"file":"LocalizeItemDialog.d.ts","sourceRoot":"","sources":["../src/LocalizeItemDialog.tsx"],"names":[],"mappings":"AA8BA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EAExB,MAAM,eAAe,CAAC;AAmEvB,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,uBAAuB,GAAG,WAAW,CAAC,uBAAuB,CAAC,2CA4gBtE"}
1
+ {"version":3,"file":"LocalizeItemDialog.d.ts","sourceRoot":"","sources":["../src/LocalizeItemDialog.tsx"],"names":[],"mappings":"AA8BA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EAExB,MAAM,eAAe,CAAC;AAmEvB,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,uBAAuB,GAAG,WAAW,CAAC,uBAAuB,CAAC,2CA8gBtE"}
@@ -290,20 +290,20 @@ 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: [_jsx(StyledDialogTitle, { icon: _jsx(GlobeIcon, { strokeWidth: 1.5 }), title: `Translate · ${currentStep?.name ?? ""}`, subtitle: currentStep?.description ||
294
- "Configure and start translation for your content" }), _jsx("div", { id: "translation-wizard-description", className: "sr-only", children: currentStep?.description ||
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
- const StepComponent = step.component;
297
- const isActive = index === currentStepIndex;
298
- if (!StepComponent)
299
- return null;
300
- return (_jsx("div", { className: "h-full", style: { display: isActive ? "block" : "none" }, "aria-hidden": !isActive, "data-testid": `step-content-${step.id}`, children: _jsx(StepComponent, { stepIndex: index, isActive: isActive, data: wizardData, setData: setWizardDataStable, editContext: editContext, onStepCompleted: (completed) => handleStepCompleted(completed, index), setBeforeNextCallback: isActive ? setBeforeNextCallbackStable : undefined, setFooterActions: isActive ? provideFooterActions : undefined, requestClose: isActive ? requestCloseCb : undefined }) }, step.id));
301
- }) }) }), _jsxs(DialogButtons, { "data-testid": "translation-wizard-dialog-buttons", children: [_jsx(Button, { onClick: () => props.onClose?.(null), variant: "ghost", size: "lg", className: "w-auto min-w-24 flex-none", "data-testid": "translation-wizard-cancel-button", children: "Cancel" }), _jsxs("div", { className: "ml-auto flex min-w-0 flex-wrap items-center justify-end gap-3", children: [currentStepIndex > 0 && (_jsx(Button, { onClick: handlePrevious, variant: "outline", size: "lg", className: "w-auto min-w-32 flex-none", "data-testid": "translation-wizard-previous-button", children: "Previous" })), footerActions.map((a) => (_jsx(Button, { onClick: a.onClick, disabled: !!a.disabled, variant: "default", size: "lg", className: "w-auto min-w-32 flex-none", "data-testid": `translation-wizard-footer-action-${a.key}`, children: a.label }, a.key))), _jsx(Button, { onClick: handleNext, disabled: !canProceed || isSubmitting, variant: "default", size: "lg", className: "w-auto min-w-40 flex-none gap-2", "data-testid": "translation-wizard-next-button", children: isSubmitting ? ("Starting...") : isLastStep ? ((() => {
302
- const { totalTranslations, isStreaming } = calculateTranslationCounts(wizardData);
303
- if (totalTranslations <= 0)
304
- return "Start Translation";
305
- return `Start Translation (${totalTranslations}${isStreaming ? "+" : ""})`;
306
- })()) : (_jsxs(_Fragment, { children: [getNextButtonLabel(activeSteps[currentStepIndex + 1]), _jsx(ArrowRightIcon, { className: "h-4 w-4", strokeWidth: 2 })] })) })] })] })] }), _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: (() => {
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.5 }), title: `Translate · ${currentStep?.name ?? ""}`, subtitle: currentStep?.description ||
294
+ "Configure and start translation for your content" }), _jsx("div", { id: "translation-wizard-description", className: "sr-only", children: currentStep?.description ||
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
+ const StepComponent = step.component;
297
+ const isActive = index === currentStepIndex;
298
+ if (!StepComponent)
299
+ return null;
300
+ return (_jsx("div", { className: "h-full", style: { display: isActive ? "block" : "none" }, "aria-hidden": !isActive, "data-testid": `step-content-${step.id}`, children: _jsx(StepComponent, { stepIndex: index, isActive: isActive, data: wizardData, setData: setWizardDataStable, editContext: editContext, onStepCompleted: (completed) => handleStepCompleted(completed, index), setBeforeNextCallback: isActive ? setBeforeNextCallbackStable : undefined, setFooterActions: isActive ? provideFooterActions : undefined, requestClose: isActive ? requestCloseCb : undefined }) }, step.id));
301
+ }) }) }), _jsxs(DialogButtons, { "data-testid": "translation-wizard-dialog-buttons", children: [_jsx(Button, { onClick: () => props.onClose?.(null), variant: "ghost", size: "lg", className: "w-auto min-w-24 flex-none", "data-testid": "translation-wizard-cancel-button", children: "Cancel" }), _jsxs("div", { className: "ml-auto flex min-w-0 flex-wrap items-center justify-end gap-3", children: [currentStepIndex > 0 && (_jsx(Button, { onClick: handlePrevious, variant: "outline", size: "lg", className: "w-auto min-w-32 flex-none", "data-testid": "translation-wizard-previous-button", children: "Previous" })), footerActions.map((a) => (_jsx(Button, { onClick: a.onClick, disabled: !!a.disabled, variant: "default", size: "lg", className: "w-auto min-w-32 flex-none", "data-testid": `translation-wizard-footer-action-${a.key}`, children: a.label }, a.key))), _jsx(Button, { onClick: handleNext, disabled: !canProceed || isSubmitting, variant: "default", size: "lg", className: "w-auto min-w-40 flex-none gap-2", "data-testid": "translation-wizard-next-button", children: isSubmitting ? ("Starting...") : isLastStep ? ((() => {
302
+ const { totalTranslations, isStreaming } = calculateTranslationCounts(wizardData);
303
+ if (totalTranslations <= 0)
304
+ return "Start Translation";
305
+ return `Start Translation (${totalTranslations}${isStreaming ? "+" : ""})`;
306
+ })()) : (_jsxs(_Fragment, { children: [getNextButtonLabel(activeSteps[currentStepIndex + 1]), _jsx(ArrowRightIcon, { className: "h-4 w-4", strokeWidth: 2 })] })) })] })] })] })] }), _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" })] })] }) })] }));
@@ -1 +1 @@
1
- {"version":3,"file":"TranslationBatches.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationBatches.tsx"],"names":[],"mappings":"AA4UA,wBAAgB,kBAAkB,4CAklCjC;AAED,eAAO,MAAM,oCAAoC,8BAA8B,CAAC;AAEhF,wBAAgB,8BAA8B,4CA0Y7C"}
1
+ {"version":3,"file":"TranslationBatches.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationBatches.tsx"],"names":[],"mappings":"AAwVA,wBAAgB,kBAAkB,4CAgnCjC;AAED,eAAO,MAAM,oCAAoC,8BAA8B,CAAC;AAEhF,wBAAgB,8BAA8B,4CA0Y7C"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useRef, useState, useMemo, useSyncExternalStore, } from "react";
3
3
  import React from "react";
4
- import { Button, Badge, Select, Input, UserPicker, Popover, PopoverContent, PopoverTrigger, Tooltip, TooltipContent, TooltipTrigger, ContentTree, PageHeader, fetchItemStubs, searchUsers as searchBackendUsers, useEditContext, getLanguages, SimpleIconButton, formatDateTime, } from "@parhelia/core";
4
+ import { Button, Badge, Select, Input, UserPicker, Popover, PopoverContent, PopoverTrigger, Tooltip, TooltipContent, TooltipTrigger, ContentTree, PageHeader, fetchItemStubs, searchUsers as searchBackendUsers, useEditContext, getLanguages, SimpleIconButton, WorkspaceHomeView, formatDateTime, } from "@parhelia/core";
5
5
  import { listBatches, getTranslationProviders, listBatchTranslationJobs, retryBatchTranslation, abortJob, abortBatch, } from "../services/translationService";
6
6
  import { TRANSLATION_BATCH_STARTED_EVENT, } from "../translationEvents";
7
7
  import { useDebouncedCallback } from "use-debounce";
@@ -174,8 +174,19 @@ function dateRangeToFromUtc(range) {
174
174
  }
175
175
  return cutoff.toISOString();
176
176
  }
177
+ const EMPTY_STATE_SLOGANS = [
178
+ "It's quiet here. In every language.",
179
+ "Zero translations. Nada. Nichts. Rien.",
180
+ "Lost in translation? Nothing to lose yet.",
181
+ "This page is fluent in emptiness.",
182
+ "The translators are on a coffee break.",
183
+ "Untranslated, unbothered, unfiltered.",
184
+ "So empty, even Esperanto gave up.",
185
+ "Say hello in every language. Soon.",
186
+ ];
177
187
  export function TranslationBatches() {
178
188
  const editContext = useEditContext();
189
+ const [emptyStateSlogan] = useState(() => EMPTY_STATE_SLOGANS[Math.floor(Math.random() * EMPTY_STATE_SLOGANS.length)]);
179
190
  const [batches, setBatches] = useState([]);
180
191
  const [sitecoreLanguages, setSitecoreLanguages] = useState([]);
181
192
  const [isLoading, setIsLoading] = useState(false);
@@ -202,6 +213,21 @@ export function TranslationBatches() {
202
213
  const rootRef = useRef(null);
203
214
  const [isCompactBatches, setIsCompactBatches] = useState(isMobile);
204
215
  const { filters } = useTranslationBatchFilterSnapshot();
216
+ const hasActiveEmptyStateFilters = filters.dateRange !== "last30days" ||
217
+ filters.status !== "all" ||
218
+ filters.user !== currentUserName ||
219
+ filters.provider !== "all" ||
220
+ filters.targetLanguage !== "all" ||
221
+ filters.itemIdOrPath.trim() !== "" ||
222
+ filters.itemIncludeSubitems;
223
+ const handleStartFirstTranslation = useCallback(() => {
224
+ if (!editContext)
225
+ return;
226
+ void openLocalizeItemDialog({
227
+ editContext,
228
+ items: editContext.item ? [editContext.item] : [],
229
+ });
230
+ }, [editContext]);
205
231
  useEffect(() => {
206
232
  const node = rootRef.current;
207
233
  if (!node)
@@ -723,20 +749,12 @@ export function TranslationBatches() {
723
749
  editContext?.setShowAgentsWorkspaceEditor(true);
724
750
  await editContext?.loadItem(language ? { id: normalized, language, version: 0 } : normalized);
725
751
  }, [editContext]);
726
- return (_jsxs("div", { ref: rootRef, className: "flex h-full min-h-0 flex-col bg-neutral-grey-5", style: { padding: isCompactBatches ? 12 : 40 }, "data-testid": "translation-batches", children: [_jsx(PageHeader, { title: "Translation Batches", description: isMobile
752
+ const showHomeView = !(isLoading && batches.length === 0) &&
753
+ groupedBatches.length === 0 &&
754
+ !hasActiveEmptyStateFilters;
755
+ return (_jsxs("div", { ref: rootRef, className: "flex h-full min-h-0 flex-col bg-neutral-grey-5", style: { padding: isCompactBatches ? 12 : 40 }, "data-testid": "translation-batches", children: [!showHomeView && (_jsx(PageHeader, { title: "Translation Batches", description: isMobile
727
756
  ? undefined
728
- : "Review translation history and manage batch progress", variant: "workspace", className: isCompactBatches ? "mb-4" : "mb-5" }), _jsx("main", { className: "min-h-0 min-w-0 flex-1 overflow-hidden rounded-[12px] bg-white", children: _jsx("div", { className: `h-full min-h-0 overflow-auto ${isCompactBatches ? "p-3" : "p-6"}`, children: isLoading && batches.length === 0 ? (_jsx("div", { className: "flex items-center justify-center h-32", children: _jsxs("div", { className: "flex items-center gap-2 text-neutral-grey-50", children: [_jsx(LoaderIcon, { className: "h-5 w-5 animate-spin text-highlight-100" }), "Loading recent translations..."] }) })) : groupedBatches.length === 0 ? (_jsx("div", { className: "flex items-center justify-center h-32", children: _jsxs("div", { className: "text-center text-neutral-grey-50", children: [_jsx(LanguagesIcon, { className: "h-8 w-8 block mx-auto mb-2 text-neutral-grey-15" }), _jsx("p", { className: "font-medium text-neutral-grey-100", children: "No translations found" }), _jsx("p", { className: "text-sm mt-1", children: (() => {
729
- const hasActiveFilters = filters.dateRange !== "last30days" ||
730
- filters.status !== "all" ||
731
- filters.user !== currentUserName ||
732
- filters.provider !== "all" ||
733
- filters.targetLanguage !== "all" ||
734
- filters.itemIdOrPath.trim() !== "" ||
735
- filters.itemIncludeSubitems;
736
- return hasActiveFilters
737
- ? "Try adjusting your filters or start a translation to see it appear here"
738
- : "Start a translation to see it appear here";
739
- })() })] }) })) : (_jsxs("div", { className: isCompactBatches ? "space-y-6" : "space-y-10", children: [groupedBatches.map((dateGroup) => (_jsxs("div", { children: [_jsxs("div", { className: "flex items-baseline gap-2 mb-2", children: [_jsx("h2", { className: "text-[11px] font-medium tracking-[0.08em] text-neutral-grey-50", children: dateGroup.label }), _jsx("span", { className: "flex-1 ml-2 border-t border-border-default" })] }), _jsx("div", { className: "divide-border-default divide-y overflow-hidden rounded-lg bg-white", children: dateGroup.batches.map((b) => {
757
+ : "Review translation history and manage batch progress", variant: "workspace", className: isCompactBatches ? "mb-4" : "mb-5" })), _jsx("main", { className: "min-h-0 min-w-0 flex-1 overflow-hidden rounded-[12px] bg-white", children: _jsx("div", { className: `h-full min-h-0 overflow-auto ${showHomeView ? "" : isCompactBatches ? "p-3" : "p-6"}`, children: isLoading && batches.length === 0 ? (_jsx("div", { className: "flex items-center justify-center h-32", children: _jsxs("div", { className: "flex items-center gap-2 text-neutral-grey-50", children: [_jsx(LoaderIcon, { className: "h-5 w-5 animate-spin text-highlight-100" }), "Loading recent translations..."] }) })) : groupedBatches.length === 0 ? (hasActiveEmptyStateFilters ? (_jsx("div", { className: "flex items-center justify-center h-32", children: _jsxs("div", { className: "text-center text-neutral-grey-50", children: [_jsx(LanguagesIcon, { className: "h-8 w-8 block mx-auto mb-2 text-neutral-grey-15" }), _jsx("p", { className: "font-medium text-neutral-grey-100", children: emptyStateSlogan }), _jsx("p", { className: "text-sm mt-1", children: "Try adjusting your filters or start a translation to see it appear here" })] }) })) : (_jsx(WorkspaceHomeView, { slogans: EMPTY_STATE_SLOGANS, actionLabel: "Start your first translation", onAction: editContext ? handleStartFirstTranslation : undefined, testId: "translation-batches-home-view", actionTestId: "translation-batches-start-translation-card" }))) : (_jsxs("div", { className: isCompactBatches ? "space-y-6" : "space-y-10", children: [groupedBatches.map((dateGroup) => (_jsxs("div", { children: [_jsxs("div", { className: "flex items-baseline gap-2 mb-2", children: [_jsx("h2", { className: "text-[11px] font-medium tracking-[0.08em] text-neutral-grey-50", children: dateGroup.label }), _jsx("span", { className: "flex-1 ml-2 border-t border-border-default" })] }), _jsx("div", { className: "divide-border-default divide-y overflow-hidden rounded-lg bg-white", children: dateGroup.batches.map((b) => {
740
758
  const batchDate = new Date(b.timestamp);
741
759
  const formattedBatchDate = formatDateTime(batchDate);
742
760
  const info = b.info;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parhelia/localization",
3
- "version": "0.1.12928",
3
+ "version": "0.1.12931",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"