@parhelia/localization 0.1.12907 → 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.
Files changed (77) hide show
  1. package/dist/LocalizeItemCommand.d.ts +7 -1
  2. package/dist/LocalizeItemCommand.d.ts.map +1 -1
  3. package/dist/LocalizeItemCommand.js +31 -18
  4. package/dist/LocalizeItemDialog.d.ts.map +1 -1
  5. package/dist/LocalizeItemDialog.js +97 -35
  6. package/dist/LocalizeItemUtils.d.ts +1 -2
  7. package/dist/LocalizeItemUtils.d.ts.map +1 -1
  8. package/dist/LocalizeItemUtils.js +78 -36
  9. package/dist/api/discovery.d.ts +25 -0
  10. package/dist/api/discovery.d.ts.map +1 -1
  11. package/dist/api/discovery.js +106 -2
  12. package/dist/hooks/useTranslationWizard.d.ts.map +1 -1
  13. package/dist/hooks/useTranslationWizard.js +3 -3
  14. package/dist/index.d.ts +10 -11
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +36 -32
  17. package/dist/services/translationService.d.ts +41 -10
  18. package/dist/services/translationService.d.ts.map +1 -1
  19. package/dist/services/translationService.js +48 -6
  20. package/dist/settings/TranslationServicesPanel.d.ts.map +1 -1
  21. package/dist/settings/TranslationServicesPanel.js +21 -36
  22. package/dist/setup/LocalizationSetupStep.d.ts.map +1 -1
  23. package/dist/setup/LocalizationSetupStep.js +29 -18
  24. package/dist/sidebar/TranslationSidebar.d.ts.map +1 -1
  25. package/dist/sidebar/TranslationSidebar.js +20 -10
  26. package/dist/steps/ItemSelectionStep.d.ts +3 -0
  27. package/dist/steps/ItemSelectionStep.d.ts.map +1 -0
  28. package/dist/steps/ItemSelectionStep.js +24 -0
  29. package/dist/steps/ItemSelectionTree.d.ts +13 -0
  30. package/dist/steps/ItemSelectionTree.d.ts.map +1 -0
  31. package/dist/steps/ItemSelectionTree.js +327 -0
  32. package/dist/steps/PromptCustomizationStep.d.ts +1 -1
  33. package/dist/steps/PromptCustomizationStep.d.ts.map +1 -1
  34. package/dist/steps/PromptCustomizationStep.js +159 -56
  35. package/dist/steps/ServiceLanguageSelectionStep.d.ts +6 -1
  36. package/dist/steps/ServiceLanguageSelectionStep.d.ts.map +1 -1
  37. package/dist/steps/ServiceLanguageSelectionStep.js +92 -165
  38. package/dist/steps/WizardStepShell.d.ts +17 -0
  39. package/dist/steps/WizardStepShell.d.ts.map +1 -0
  40. package/dist/steps/WizardStepShell.js +11 -0
  41. package/dist/steps/types.d.ts +17 -1
  42. package/dist/steps/types.d.ts.map +1 -1
  43. package/dist/translation-center/TranslationBatches.d.ts +2 -0
  44. package/dist/translation-center/TranslationBatches.d.ts.map +1 -0
  45. package/dist/translation-center/TranslationBatches.js +1180 -0
  46. package/dist/translation-center/TranslationManagement.d.ts.map +1 -1
  47. package/dist/translation-center/TranslationManagement.js +25 -15
  48. package/dist/translation-center/TranslationsTitlebar.d.ts +6 -0
  49. package/dist/translation-center/TranslationsTitlebar.d.ts.map +1 -0
  50. package/dist/translation-center/TranslationsTitlebar.js +25 -0
  51. package/dist/translationEvents.d.ts +6 -0
  52. package/dist/translationEvents.d.ts.map +1 -0
  53. package/dist/translationEvents.js +4 -0
  54. package/dist/types.d.ts +1 -0
  55. package/dist/types.d.ts.map +1 -1
  56. package/package.json +1 -1
  57. package/dist/constants.d.ts +0 -15
  58. package/dist/constants.d.ts.map +0 -1
  59. package/dist/constants.js +0 -21
  60. package/dist/steps/MetadataInputStep.d.ts +0 -4
  61. package/dist/steps/MetadataInputStep.d.ts.map +0 -1
  62. package/dist/steps/MetadataInputStep.js +0 -41
  63. package/dist/steps/SubitemDiscoveryStep.d.ts +0 -3
  64. package/dist/steps/SubitemDiscoveryStep.d.ts.map +0 -1
  65. package/dist/steps/SubitemDiscoveryStep.js +0 -313
  66. package/dist/steps/index.d.ts +0 -5
  67. package/dist/steps/index.d.ts.map +0 -1
  68. package/dist/steps/index.js +0 -4
  69. package/dist/translation-center/BatchTranslationView.d.ts +0 -8
  70. package/dist/translation-center/BatchTranslationView.d.ts.map +0 -1
  71. package/dist/translation-center/BatchTranslationView.js +0 -870
  72. package/dist/translation-center/RecentTranslations.d.ts +0 -2
  73. package/dist/translation-center/RecentTranslations.d.ts.map +0 -1
  74. package/dist/translation-center/RecentTranslations.js +0 -309
  75. package/dist/utils/createVersions.d.ts +0 -14
  76. package/dist/utils/createVersions.d.ts.map +0 -1
  77. package/dist/utils/createVersions.js +0 -26
@@ -1 +1 @@
1
- {"version":3,"file":"TranslationManagement.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationManagement.tsx"],"names":[],"mappings":"AAQA,wBAAgB,qBAAqB,4CA+CpC"}
1
+ {"version":3,"file":"TranslationManagement.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationManagement.tsx"],"names":[],"mappings":"AAOA,wBAAgB,qBAAqB,4CAwEpC"}
@@ -1,23 +1,33 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEditContext, usePathname, useRouter, useSearchParams, } from "@parhelia/core";
3
- import { BatchTranslationView } from "./BatchTranslationView";
2
+ import { ItemEditorPane, Splitter, useEditContext, } from "@parhelia/core";
4
3
  export function TranslationManagement() {
5
4
  const editContext = useEditContext();
6
5
  const config = editContext?.configuration;
7
- const searchParams = useSearchParams();
8
- const batchId = searchParams.get("batchId");
9
- const router = useRouter();
10
- const pathname = usePathname();
11
- // Get the Recent Translations panel content (since it's the only one)
12
- const recentTranslationsPanel = config?.translationCenter?.groups
6
+ const showEditorPanel = editContext?.showAgentsWorkspaceEditor ?? false;
7
+ const isMobile = editContext?.isMobile ?? false;
8
+ // Get the Translation Batches panel content (since it's the only one)
9
+ const translationBatchesPanel = config?.translationCenter?.groups
13
10
  ?.flatMap((x) => x.panels)
14
- ?.find((panel) => panel.id === "recent-translations");
11
+ ?.find((panel) => panel.id === "translation-batches");
15
12
  if (!config) {
16
- return (_jsx("div", { className: "flex h-full flex-col items-center justify-center bg-[var(--color-gray-5)]", children: _jsxs("div", { className: "flex items-center gap-2 text-[var(--color-gray-2)]", children: [_jsx("i", { className: "pi pi-spin pi-spinner text-[#9650fb]" }), "Loading..."] }) }));
13
+ return (_jsx("div", { className: "flex h-full flex-col items-center justify-center bg-neutral-grey-5", children: _jsxs("div", { className: "flex items-center gap-2 text-neutral-grey-50", children: [_jsx("i", { className: "pi pi-spin pi-spinner text-[var(--color-highlight-100)]" }), "Loading..."] }) }));
17
14
  }
18
- return (_jsx("div", { className: "absolute inset-0 flex flex-col bg-[var(--color-gray-5)]", "data-testid": "translation-management", children: batchId ? (_jsx(BatchTranslationView, { batchId: batchId, onBack: () => {
19
- const current = new URLSearchParams(searchParams.toString());
20
- current.delete("batchId");
21
- router.push(`${pathname}?${current.toString()}`, { scroll: false });
22
- } })) : recentTranslationsPanel ? (_jsx("div", { className: "flex-1 min-h-0", children: recentTranslationsPanel.content })) : (_jsxs("div", { className: "flex h-full flex-col items-center justify-center text-[var(--color-gray-2)]", children: [_jsx("i", { className: "pi pi-language mb-4 text-4xl text-[var(--color-gray-3)]" }), _jsx("p", { className: "font-medium text-[var(--color-gray-1)]", children: "Recent translations not available" })] })) }));
15
+ const managementContent = translationBatchesPanel ? (_jsx("div", { className: "h-full min-h-0 overflow-hidden", children: translationBatchesPanel.content })) : (_jsxs("div", { className: "flex h-full min-h-0 flex-col items-center justify-center text-neutral-grey-50", children: [_jsx("i", { className: "pi pi-language mb-4 text-4xl text-neutral-grey-15" }), _jsx("p", { className: "font-medium text-neutral-grey-100", children: "Translation batches not available" })] }));
16
+ const panels = [
17
+ {
18
+ name: "translation-management",
19
+ defaultSize: "auto",
20
+ content: managementContent,
21
+ className: "h-full min-h-0 min-w-0",
22
+ },
23
+ ];
24
+ if (showEditorPanel) {
25
+ panels.push({
26
+ name: "editor-preview",
27
+ defaultSize: isMobile ? 45 : 500,
28
+ className: "h-full min-h-0 min-w-0",
29
+ content: (_jsx("div", { className: "h-full overflow-hidden border-l border-border-default bg-neutral-grey-5", children: _jsx(ItemEditorPane, { name: "translation-management-preview", emptyDescription: "Select a translation batch item or language row to preview and edit it here." }) })),
30
+ });
31
+ }
32
+ return (_jsx("div", { className: "absolute inset-0 flex min-h-0 flex-col overflow-hidden bg-neutral-grey-5", "data-testid": "translation-management", children: _jsx(Splitter, { panels: panels, direction: isMobile ? "vertical" : "horizontal", localStorageKey: "translation-management.panelSizes" }) }));
23
33
  }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * TranslationsTitlebar - Titlebar content for the Translation Management workspace.
3
+ * Shows desktop actions for the Translation Management workspace.
4
+ */
5
+ export declare function TranslationsTitlebar(): import("react/jsx-runtime").JSX.Element | null;
6
+ //# sourceMappingURL=TranslationsTitlebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TranslationsTitlebar.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationsTitlebar.tsx"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,oBAAoB,mDA8CnC"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, SimpleIconButton, useEditContext } from "@parhelia/core";
3
+ import { Globe, SquarePen } from "lucide-react";
4
+ import { openLocalizeItemDialog } from "../LocalizeItemCommand";
5
+ /**
6
+ * TranslationsTitlebar - Titlebar content for the Translation Management workspace.
7
+ * Shows desktop actions for the Translation Management workspace.
8
+ */
9
+ export function TranslationsTitlebar() {
10
+ const editContext = useEditContext();
11
+ if (!editContext?.workspace)
12
+ return null;
13
+ if (editContext.isMobile)
14
+ return null;
15
+ const { showAgentsWorkspaceEditor, setShowAgentsWorkspaceEditor } = editContext;
16
+ const multiItemEnabled = editContext.configuration?.localization?.multiItem !== false;
17
+ const currentItem = editContext.item;
18
+ const canTranslate = multiItemEnabled || !!currentItem;
19
+ return (_jsxs("div", { className: "flex w-full items-center justify-between gap-3 pr-2", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [_jsx("div", { "aria-hidden": "true", className: "border-border-default h-7 shrink-0 border-r" }), _jsxs(Button, { size: "sm", title: canTranslate ? "Translate" : "Open an item to translate", "data-testid": "translations-titlebar-translate-button", disabled: !canTranslate, onClick: () => {
20
+ void openLocalizeItemDialog({
21
+ editContext,
22
+ items: currentItem ? [currentItem] : [],
23
+ });
24
+ }, children: [_jsx(Globe, { className: "h-4 w-4", strokeWidth: 1.5 }), "Translate"] })] }), _jsx(SimpleIconButton, { icon: _jsx(SquarePen, { className: "h-5 w-5", strokeWidth: 1 }), label: showAgentsWorkspaceEditor ? "Hide Editor" : "Show Editor", size: "large", "data-testid": "translations-editor-panel-toggle", selected: showAgentsWorkspaceEditor, onClick: () => setShowAgentsWorkspaceEditor(!showAgentsWorkspaceEditor) })] }));
25
+ }
@@ -0,0 +1,6 @@
1
+ export declare const TRANSLATION_BATCH_STARTED_EVENT = "parhelia:translation-batch-started";
2
+ export type TranslationBatchStartedEventDetail = {
3
+ batchId: string;
4
+ };
5
+ export declare function dispatchTranslationBatchStarted(batchId: string): void;
6
+ //# sourceMappingURL=translationEvents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translationEvents.d.ts","sourceRoot":"","sources":["../src/translationEvents.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,+BAA+B,uCACN,CAAC;AAEvC,MAAM,MAAM,kCAAkC,GAAG;IAC/C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,QAO9D"}
@@ -0,0 +1,4 @@
1
+ export const TRANSLATION_BATCH_STARTED_EVENT = "parhelia:translation-batch-started";
2
+ export function dispatchTranslationBatchStarted(batchId) {
3
+ window.dispatchEvent(new CustomEvent(TRANSLATION_BATCH_STARTED_EVENT, { detail: { batchId } }));
4
+ }
package/dist/types.d.ts CHANGED
@@ -7,6 +7,7 @@ export type TranslationStatus = {
7
7
  status: string;
8
8
  timestamp: string;
9
9
  message?: string;
10
+ totalCost?: number | null;
10
11
  };
11
12
  export type translationCenter = {
12
13
  groups: {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,SAAS,CAAC;QAChB,MAAM,EAAE,aAAa,EAAE,CAAC;KACzB,EAAE,CAAC;CACL,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,SAAS,CAAC;QAChB,MAAM,EAAE,aAAa,EAAE,CAAC;KACzB,EAAE,CAAC;CACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parhelia/localization",
3
- "version": "0.1.12907",
3
+ "version": "0.1.12909",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -1,15 +0,0 @@
1
- export declare const DISCOVERY_CONFIRMATION_THRESHOLD = 100;
2
- export declare const EXCLUDED_TEMPLATE_IDS: string[];
3
- export declare const DIALOG_DIMENSIONS: {
4
- width: string;
5
- height: string;
6
- };
7
- export declare const STEP_STATES: {
8
- readonly COMPLETED: "completed";
9
- readonly CURRENT: "current";
10
- readonly PENDING: "pending";
11
- };
12
- export declare const STORAGE_KEYS: {
13
- readonly TRANSLATION_PROVIDER: "editor.translationProvider";
14
- };
15
- //# sourceMappingURL=constants.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAGpD,eAAO,MAAM,qBAAqB,UAEjC,CAAC;AAGF,eAAO,MAAM,iBAAiB;;;CAG7B,CAAC;AAGF,eAAO,MAAM,WAAW;;;;CAId,CAAC;AAGX,eAAO,MAAM,YAAY;;CAEf,CAAC"}
package/dist/constants.js DELETED
@@ -1,21 +0,0 @@
1
- // Discovery configuration
2
- export const DISCOVERY_CONFIRMATION_THRESHOLD = 100; // Pause every N subitems
3
- // Template IDs to exclude from translation
4
- export const EXCLUDED_TEMPLATE_IDS = [
5
- "de8bfdac-5f9f-40c3-a680-2fce9997ae28" // System template ID
6
- ];
7
- // Dialog dimensions
8
- export const DIALOG_DIMENSIONS = {
9
- width: "75vw",
10
- height: "75vh"
11
- };
12
- // Step progress indicators
13
- export const STEP_STATES = {
14
- COMPLETED: "completed",
15
- CURRENT: "current",
16
- PENDING: "pending"
17
- };
18
- // Local storage keys
19
- export const STORAGE_KEYS = {
20
- TRANSLATION_PROVIDER: "editor.translationProvider"
21
- };
@@ -1,4 +0,0 @@
1
- import { TranslationStepProps } from "./types";
2
- /** Example Step for metadata input testing */
3
- export declare function MetadataInputStep({ stepIndex, isActive, data, setData, onStepCompleted, }: TranslationStepProps): import("react/jsx-runtime").JSX.Element;
4
- //# sourceMappingURL=MetadataInputStep.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MetadataInputStep.d.ts","sourceRoot":"","sources":["../../src/steps/MetadataInputStep.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE/C,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,QAAe,EACf,IAAI,EACJ,OAAO,EACP,eAAe,GAChB,EAAE,oBAAoB,2CA8EtB"}
@@ -1,41 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect } from "react";
3
- /** Example Step for metadata input testing */
4
- export function MetadataInputStep({ stepIndex, isActive = true, data, setData, onStepCompleted, }) {
5
- // Convert Map<string, Map<string, string>> to a flat object for local state management
6
- const [itemMetadata, setItemMetadata] = useState(() => {
7
- const result = {};
8
- data.itemMetadata.forEach((languageMap, itemId) => {
9
- result[itemId] = Object.fromEntries(languageMap);
10
- });
11
- return result;
12
- });
13
- const allItems = data.includeSubitems ? data.discoveredItems : data.items;
14
- const handleMetadataChange = (itemId, language, metadata) => {
15
- const updated = {
16
- ...itemMetadata,
17
- [itemId]: {
18
- ...(itemMetadata[itemId] || {}),
19
- [language]: metadata
20
- }
21
- };
22
- setItemMetadata(updated);
23
- // Convert back to Map structure for wizard data
24
- const metadataMap = new Map();
25
- Object.entries(updated).forEach(([itemId, languageMap]) => {
26
- metadataMap.set(itemId, new Map(Object.entries(languageMap)));
27
- });
28
- setData({ ...data, itemMetadata: metadataMap });
29
- console.log('Updated itemMetadata:', metadataMap);
30
- };
31
- // Data is saved automatically on change
32
- useEffect(() => {
33
- // Only update completion when this step is active
34
- if (!isActive)
35
- return;
36
- // Mark step as completed since metadata is optional
37
- onStepCompleted(true);
38
- }, [isActive, onStepCompleted]); // Check when active state changes
39
- // No footer actions needed since data is saved automatically
40
- return (_jsxs("div", { className: "flex flex-col gap-4 p-6", "data-testid": "metadata-input-step", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-xl font-semibold text-[var(--color-dark)] mb-2", children: "Enter Metadata Per Item Per Language" }), _jsx("p", { className: "text-sm text-[var(--color-gray-2)]", children: "Provide custom metadata for each item and language combination (optional)." })] }), _jsx("div", { className: "max-h-64 overflow-y-auto space-y-4", "data-testid": "metadata-input-container", children: allItems.map((item) => (_jsxs("div", { className: "border border-[var(--color-gray-3)] rounded-lg p-4 bg-background shadow-sm", "data-testid": `metadata-item-${item.id}`, children: [_jsx("label", { className: "block text-sm font-medium text-[var(--color-dark)] mb-3", "data-testid": `metadata-item-label-${item.id}`, children: item.name || item.id }), data.targetLanguages?.map((language) => (_jsxs("div", { className: "mb-3", "data-testid": `metadata-field-${item.id}-${language}`, children: [_jsxs("label", { className: "block text-xs font-medium mb-1.5 text-[var(--color-gray-2)]", "data-testid": `metadata-language-label-${item.id}-${language}`, children: [language.toUpperCase(), ":"] }), _jsx("textarea", { className: "w-full border border-[var(--color-gray-3)] rounded-md p-2.5 text-sm bg-[var(--color-gray-5)] text-[var(--color-dark)] focus:outline-none focus:ring-2 focus:ring-[#9650fb] focus:border-[#9650fb] transition-colors", rows: 2, value: itemMetadata[item.id]?.[language] || "", onChange: (e) => handleMetadataChange(item.id, language, e.target.value), placeholder: `Enter metadata for ${language}...`, "data-testid": `metadata-textarea-${item.id}-${language}` })] }, `${item.id}-${language}`)))] }, item.id))) })] }));
41
- }
@@ -1,3 +0,0 @@
1
- import { TranslationStepProps } from "./types";
2
- export declare function SubitemDiscoveryStep({ stepIndex, isActive, data, setData, editContext, onStepCompleted, setBeforeNextCallback, setFooterActions, requestClose }: TranslationStepProps): import("react/jsx-runtime").JSX.Element;
3
- //# sourceMappingURL=SubitemDiscoveryStep.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SubitemDiscoveryStep.d.ts","sourceRoot":"","sources":["../../src/steps/SubitemDiscoveryStep.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAW/C,wBAAgB,oBAAoB,CAAC,EAAE,SAAS,EAAE,QAAe,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,YAAY,EAAE,EAAE,oBAAoB,2CAga5L"}
@@ -1,313 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useState, useRef, useMemo, useCallback } from "react";
3
- import { Button, PerfectTree } from "@parhelia/core";
4
- import { convertFullItemToStub, convertStubToFullItem } from "@parhelia/core";
5
- import { discoverItemsTree, convertBackendTreeToTreeNodes, flattenSelectableItemsFromBackendTrees } from "../api/discovery";
6
- // We need to implement a basic Spinner component since it's not in core
7
- const Spinner = ({ ...props }) => (_jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-[#9650fb]", ...props }));
8
- export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData, editContext, onStepCompleted, setBeforeNextCallback, setFooterActions, requestClose }) {
9
- // Core state - simplified
10
- const [isDiscovering, setIsDiscovering] = useState(false);
11
- const [discoveryComplete, setDiscoveryComplete] = useState(false);
12
- const [selectedItemIds, setSelectedItemIds] = useState(new Set());
13
- const [treeNodes, setTreeNodes] = useState([]);
14
- const [allDiscoveredItems, setAllDiscoveredItems] = useState([]);
15
- const [userHasInteracted, setUserHasInteracted] = useState(false);
16
- const [discoveredCount, setDiscoveredCount] = useState(0);
17
- const [totalItemsCount, setTotalItemsCount] = useState(0);
18
- const [treeInitialized, setTreeInitialized] = useState(false);
19
- const [expandedIds, setExpandedIds] = useState(new Set());
20
- // Refs for async safety
21
- const isMountedRef = useRef(true);
22
- const inFlightRef = useRef(false);
23
- const shiftToggleRef = useRef(false);
24
- // Cleanup
25
- useEffect(() => {
26
- isMountedRef.current = true;
27
- return () => { isMountedRef.current = false; };
28
- }, []);
29
- // Commit callback - simplified
30
- useEffect(() => {
31
- const commit = async () => {
32
- const selectedItems = allDiscoveredItems.filter(item => selectedItemIds.has(item.id));
33
- const convertedItems = selectedItems.map(convertStubToFullItem);
34
- setData({ ...data, discoveredItems: convertedItems });
35
- return true;
36
- };
37
- setBeforeNextCallback?.(commit);
38
- }, [setBeforeNextCallback, allDiscoveredItems, selectedItemIds, setData, data]);
39
- // Initialize discovery or simple display
40
- useEffect(() => {
41
- if (!data.includeSubitems) {
42
- // Simple mode: just show base items
43
- const stubs = data.items.map(convertFullItemToStub);
44
- setAllDiscoveredItems(stubs);
45
- setDiscoveredCount(stubs.length);
46
- const nodes = buildTreeNodes(stubs);
47
- setTreeNodes(nodes);
48
- setExpandedIds(new Set(nodes.map(n => n.key)));
49
- const countItems = (nodeList) => {
50
- let total = 0;
51
- const walk = (nodeList) => {
52
- nodeList.forEach(node => {
53
- total++;
54
- if (node.children)
55
- walk(node.children);
56
- });
57
- };
58
- walk(nodeList);
59
- return total;
60
- };
61
- setTotalItemsCount(countItems(nodes));
62
- setDiscoveryComplete(true);
63
- setTreeInitialized(true);
64
- return;
65
- }
66
- // Discovery mode: fetch tree from backend
67
- if (inFlightRef.current)
68
- return;
69
- inFlightRef.current = true;
70
- const runDiscovery = async () => {
71
- setIsDiscovering(true);
72
- try {
73
- const rootIds = data.items.map(i => i.descriptor.id);
74
- const resp = await discoverItemsTree({
75
- rootItemIds: rootIds,
76
- language: editContext?.item?.language ??
77
- editContext?.currentItemDescriptor?.language ??
78
- "en",
79
- }, editContext.sessionId ?? undefined);
80
- if (!isMountedRef.current)
81
- return;
82
- const items = flattenSelectableItemsFromBackendTrees(resp.trees);
83
- const language = editContext?.item?.language ??
84
- editContext?.currentItemDescriptor?.language ??
85
- "en";
86
- const stubs = items.map(x => ({
87
- id: x.id,
88
- name: x.name,
89
- path: x.path,
90
- parentId: "",
91
- idPath: "",
92
- database: "master",
93
- descriptor: { id: x.id, language, version: 0 },
94
- icon: "",
95
- largeIcon: "",
96
- templateId: "",
97
- templateName: "",
98
- hasLayout: false,
99
- hasChildren: x.hasChildren,
100
- versions: 0,
101
- language,
102
- version: 0,
103
- }));
104
- setAllDiscoveredItems(stubs);
105
- setDiscoveredCount(stubs.length);
106
- const nodes = convertBackendTreeToTreeNodes(resp.trees);
107
- setTreeNodes(nodes);
108
- setExpandedIds(new Set(nodes.map(n => n.key)));
109
- const countItems = (nodeList) => {
110
- let total = 0;
111
- const walk = (nodeList) => {
112
- nodeList.forEach(node => {
113
- total++;
114
- if (node.children)
115
- walk(node.children);
116
- });
117
- };
118
- walk(nodeList);
119
- return total;
120
- };
121
- setTotalItemsCount(countItems(nodes));
122
- setDiscoveryComplete(true);
123
- setTreeInitialized(true);
124
- }
125
- catch (error) {
126
- console.error("Discovery error:", error);
127
- }
128
- finally {
129
- if (isMountedRef.current)
130
- setIsDiscovering(false);
131
- inFlightRef.current = false;
132
- }
133
- };
134
- runDiscovery();
135
- }, [data.items, data.includeSubitems, editContext]);
136
- // Set initial selection when tree is ready
137
- useEffect(() => {
138
- if (!isActive || !discoveryComplete || treeNodes.length === 0 || userHasInteracted)
139
- return;
140
- let initialSelection;
141
- if (data.discoveredItems?.length > 0) {
142
- // Restore previous selection
143
- initialSelection = new Set(data.discoveredItems.map(item => item.descriptor.id));
144
- }
145
- else {
146
- // Default: select all selectable items in the tree
147
- const allSelectableIds = new Set();
148
- const walk = (nodes) => {
149
- nodes.forEach(node => {
150
- if (node?.data?.isFolder !== true) {
151
- allSelectableIds.add(node.key);
152
- }
153
- if (node.children)
154
- walk(node.children);
155
- });
156
- };
157
- walk(treeNodes);
158
- initialSelection = allSelectableIds;
159
- }
160
- setSelectedItemIds(initialSelection);
161
- }, [isActive, discoveryComplete, treeNodes, data.discoveredItems, userHasInteracted]);
162
- // Update completion status
163
- useEffect(() => {
164
- if (isActive && discoveryComplete) {
165
- onStepCompleted(selectedItemIds.size > 0);
166
- }
167
- }, [isActive, discoveryComplete, selectedItemIds.size, onStepCompleted]);
168
- const buildTreeNodes = useCallback((items) => {
169
- // Fallback: Build simple tree from items for non-subitem discovery
170
- const itemMap = new Map();
171
- const childrenMap = new Map();
172
- items.forEach(item => {
173
- itemMap.set(item.id, item);
174
- if (item.parentId) {
175
- if (!childrenMap.has(item.parentId))
176
- childrenMap.set(item.parentId, []);
177
- childrenMap.get(item.parentId).push(item);
178
- }
179
- });
180
- const buildNode = (item) => ({
181
- key: item.id,
182
- label: item.name || item.id,
183
- data: { id: item.id, name: item.name, path: item.path, isFolder: item.hasLayout !== true, hasChildren: item.hasChildren },
184
- children: (childrenMap.get(item.id) || []).map(buildNode)
185
- });
186
- const originalItemIds = new Set(data.items.map(item => item.descriptor.id));
187
- const rootItems = items.filter(item => !item.parentId || !itemMap.has(item.parentId) || originalItemIds.has(item.id));
188
- return rootItems.map(buildNode);
189
- }, [data.items]);
190
- // PerfectTree integrations
191
- const expandedKeys = useMemo(() => Array.from(expandedIds), [expandedIds]);
192
- const selectedKeys = useMemo(() => Array.from(selectedItemIds), [selectedItemIds]);
193
- const getDescendantIds = (nodeKey) => {
194
- const findNode = (nodes) => {
195
- for (const node of nodes) {
196
- if (node.key === nodeKey)
197
- return node;
198
- if (node.children) {
199
- const found = findNode(node.children);
200
- if (found)
201
- return found;
202
- }
203
- }
204
- return null;
205
- };
206
- const node = findNode(treeNodes);
207
- if (!node?.children)
208
- return [];
209
- const descendants = [];
210
- const traverse = (children) => {
211
- children.forEach(child => {
212
- descendants.push(child.key);
213
- if (child.children)
214
- traverse(child.children);
215
- });
216
- };
217
- traverse(node.children);
218
- return descendants;
219
- };
220
- const handleCancel = () => {
221
- // Simplified cancel - just stop discovery
222
- inFlightRef.current = false;
223
- setIsDiscovering(false);
224
- setDiscoveryComplete(true);
225
- };
226
- const showDiscoveryStatus = isDiscovering || !discoveryComplete;
227
- return (_jsx("div", { className: "flex h-full min-h-0 flex-col gap-4 p-6", "data-testid": "subitem-discovery-step", children: _jsxs("div", { className: "flex min-h-0 w-full min-w-0 flex-1 flex-col rounded-lg border border-[var(--color-gray-3)] bg-background p-4 shadow-sm", "data-testid": "discovery-status-container", children: [showDiscoveryStatus && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mb-4 flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [isDiscovering && _jsx(Spinner, { "data-testid": "discovery-spinner" }), _jsx("span", { className: "font-medium text-[var(--color-dark)]", "data-testid": "discovery-status-text", children: isDiscovering ? 'Discovering subitems...' : 'Ready to discover' })] }), isDiscovering && (_jsx(Button, { size: "sm", variant: "outline", onClick: handleCancel, "data-testid": "discovery-cancel-button", children: "Cancel" }))] }), _jsx("div", { className: "mb-3 text-sm text-[var(--color-gray-2)]", "data-testid": "discovery-summary", children: discoveredCount > 0 ? (_jsxs("p", { "data-testid": "discovery-total-count", children: [_jsxs("span", { className: "font-medium text-[#9650fb]", children: [totalItemsCount, " total items found"] }), _jsx("br", {}), _jsxs("span", { className: "text-xs text-[var(--color-gray-2)]", children: ["Original items: ", data.items.length, " | Subitems discovered: ", Math.max(0, totalItemsCount - data.items.length)] }), isDiscovering && (_jsxs(_Fragment, { children: [_jsx("br", {}), _jsx("span", { className: "text-xs text-[var(--color-gray-2)] italic", children: "Item tree will appear when discovery completes" })] }))] })) : (_jsx("p", { className: "text-[var(--color-gray-2)]", children: "No items discovered yet." })) })] })), _jsx("div", { className: showDiscoveryStatus ? "mt-4 flex min-h-0 flex-1 flex-col" : "flex min-h-0 flex-1 flex-col", children: !isDiscovering && discoveryComplete && treeInitialized && allDiscoveredItems.length > 0 && treeNodes.length > 0 ? (_jsxs("div", { className: "flex min-h-0 w-full min-w-0 flex-1 flex-col", "data-testid": "item-selection-section", children: [_jsxs("div", { className: showDiscoveryStatus ? "mb-3 flex flex-col gap-2 border-t border-[var(--color-gray-3)] pt-4" : "mb-3 flex flex-col gap-2", children: [_jsx("h3", { className: "text-lg font-semibold text-[var(--color-dark)]", children: "Select Items to Translate" }), _jsx("span", { className: "text-sm text-[var(--color-gray-2)]", "data-testid": "selection-summary-header", children: selectedItemIds.size > 0 ? _jsxs(_Fragment, { children: [_jsx("span", { className: "font-medium text-[#9650fb]", children: selectedItemIds.size }), " selected"] }) : "No items selected" }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Button, { size: "sm", variant: "outline", onClick: () => {
228
- if (!isActive)
229
- return;
230
- const allIds = new Set();
231
- const walk = (nodes) => {
232
- nodes.forEach(node => {
233
- allIds.add(node.key);
234
- if (node.children)
235
- walk(node.children);
236
- });
237
- };
238
- walk(treeNodes);
239
- setUserHasInteracted(true);
240
- setSelectedItemIds(allIds);
241
- onStepCompleted(allIds.size > 0);
242
- }, "data-testid": "select-all-items-button", children: "Select All" }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => {
243
- if (!isActive)
244
- return;
245
- setUserHasInteracted(true);
246
- setSelectedItemIds(new Set());
247
- onStepCompleted(false);
248
- }, "data-testid": "select-none-items-button", children: "Select None" })] })] }), _jsx("div", { className: "text-xs text-[var(--color-gray-2)] mb-3", "data-testid": "selection-summary", children: _jsx("span", { children: "Tip: Hold Shift and click a checkbox to toggle all descendants." }) }), treeNodes.length > 0 && (_jsx("div", { className: "min-h-0 w-full min-w-0 flex-1 overflow-auto rounded-lg border border-[var(--color-gray-3)] bg-[var(--color-gray-5)]", "data-testid": "item-tree-view", children: _jsx(PerfectTree, { nodes: treeNodes, expandedKeys: expandedKeys, selectedKeys: selectedKeys, onToggleExpand: (key) => {
249
- setExpandedIds(prev => {
250
- const next = new Set(prev);
251
- if (next.has(key))
252
- next.delete(key);
253
- else
254
- next.add(key);
255
- return next;
256
- });
257
- }, onSelect: (key, event) => {
258
- if (!isActive)
259
- return; // Don't handle selection when inactive
260
- setUserHasInteracted(true);
261
- const targetNode = key;
262
- const shift = event?.shiftKey === true;
263
- const next = new Set(selectedItemIds);
264
- const findNode = (nodes) => {
265
- for (const n of nodes) {
266
- if (n.key === targetNode)
267
- return n;
268
- if (n.children) {
269
- const f = findNode(n.children);
270
- if (f)
271
- return f;
272
- }
273
- }
274
- return null;
275
- };
276
- const n = findNode(treeNodes);
277
- if (!n)
278
- return;
279
- const ids = shift ? [key, ...getDescendantIds(key)] : [key];
280
- if (!next.has(key))
281
- ids.forEach((id) => next.add(id));
282
- else
283
- ids.forEach((id) => next.delete(id));
284
- setSelectedItemIds(next);
285
- // Update completion when user changes selection
286
- onStepCompleted(next.size > 0);
287
- }, renderNode: (node) => {
288
- const isChecked = selectedItemIds.has(node.key);
289
- const icon = node?.data?.icon;
290
- return (_jsxs("div", { className: "flex items-center gap-2", children: [icon && (_jsx("img", { src: icon, alt: "", className: "w-4 h-4" })), _jsx("input", { type: "checkbox", checked: isChecked, "data-testid": `tree-item-checkbox-${node.key}`, onMouseDown: (e) => {
291
- shiftToggleRef.current = e.shiftKey;
292
- }, onChange: (e) => {
293
- if (!isActive)
294
- return;
295
- setUserHasInteracted(true);
296
- const next = new Set(selectedItemIds);
297
- const withDesc = shiftToggleRef.current && (node.children?.length ?? 0) > 0;
298
- const ids = withDesc ? [node.key, ...getDescendantIds(node.key)] : [node.key];
299
- if (e.currentTarget.checked)
300
- ids.forEach((id) => next.add(id));
301
- else
302
- ids.forEach((id) => next.delete(id));
303
- setSelectedItemIds(next);
304
- shiftToggleRef.current = false;
305
- // Update completion when user changes selection
306
- onStepCompleted(next.size > 0);
307
- } }), _jsx("span", { children: node.label })] }));
308
- } }) }))] })) : isDiscovering ? (
309
- // Loading skeleton for discovery results
310
- _jsxs("div", { className: "flex w-full min-w-0 flex-col", children: [_jsx("div", { className: "p-3 bg-[#f6eeff] border border-[#9650fb]/20 rounded-lg mb-4", children: _jsx("div", { className: "h-4 bg-[#9650fb]/20 rounded w-64 animate-pulse" }) }), _jsxs("div", { className: "flex min-h-0 flex-1 flex-col border-t border-[var(--color-gray-3)] pt-4", children: [_jsxs("div", { className: "mb-3 flex flex-col gap-2", children: [_jsx("div", { className: "h-6 bg-[var(--color-gray-3)] rounded w-48 animate-pulse" }), _jsx("div", { className: "h-4 bg-[var(--color-gray-3)] rounded w-40 animate-pulse" }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx("div", { className: "h-8 bg-[var(--color-gray-3)] rounded w-20 animate-pulse" }), _jsx("div", { className: "h-8 bg-[var(--color-gray-3)] rounded w-20 animate-pulse" })] })] }), _jsx("div", { className: "h-4 bg-[var(--color-gray-3)] rounded w-64 mb-3 animate-pulse" }), _jsx("div", { className: "min-h-0 flex-1 overflow-auto rounded-lg border border-[var(--color-gray-3)] bg-[var(--color-gray-5)]", children: _jsx("div", { className: "p-3 space-y-2", children: [...Array(8)].map((_, i) => (_jsxs("div", { className: "flex items-center gap-3 animate-pulse", children: [_jsx("div", { className: "h-4 w-4 bg-[var(--color-gray-3)] rounded" }), _jsx("div", { className: "h-4 bg-[var(--color-gray-3)] rounded w-48" })] }, i))) }) })] })] })) : (
311
- // Empty state
312
- _jsx("div", { className: "flex h-80 shrink-0 items-center justify-center overflow-auto rounded-lg border border-[var(--color-gray-3)] bg-[var(--color-gray-5)]", children: _jsxs("div", { className: "text-center text-[var(--color-gray-2)]", children: [_jsx("p", { className: "font-medium text-[var(--color-gray-1)]", children: "Ready to discover subitems" }), _jsx("p", { className: "text-sm mt-1", children: "Discovery will start automatically" })] }) })) })] }) }));
313
- }
@@ -1,5 +0,0 @@
1
- export { ServiceLanguageSelectionStep } from "./ServiceLanguageSelectionStep";
2
- export { SubitemDiscoveryStep } from "./SubitemDiscoveryStep";
3
- export { MetadataInputStep } from "./MetadataInputStep";
4
- export * from "./types";
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/steps/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,cAAc,SAAS,CAAC"}
@@ -1,4 +0,0 @@
1
- export { ServiceLanguageSelectionStep } from "./ServiceLanguageSelectionStep";
2
- export { SubitemDiscoveryStep } from "./SubitemDiscoveryStep";
3
- export { MetadataInputStep } from "./MetadataInputStep";
4
- export * from "./types";
@@ -1,8 +0,0 @@
1
- import "react-json-view-lite/dist/index.css";
2
- interface BatchTranslationViewProps {
3
- batchId: string;
4
- onBack?: () => void;
5
- }
6
- export declare function BatchTranslationView({ batchId, onBack, }: BatchTranslationViewProps): import("react/jsx-runtime").JSX.Element;
7
- export {};
8
- //# sourceMappingURL=BatchTranslationView.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BatchTranslationView.d.ts","sourceRoot":"","sources":["../../src/translation-center/BatchTranslationView.tsx"],"names":[],"mappings":"AA4CA,OAAO,qCAAqC,CAAC;AA4C7C,UAAU,yBAAyB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAwED,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,MAAM,GACP,EAAE,yBAAyB,2CAmoD3B"}