@parhelia/localization 0.1.10745
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/LICENSE +8 -0
- package/README.md +29 -0
- package/dist/core/src/editor/ui/DragPreview.d.ts +15 -0
- package/dist/core/src/editor/ui/DragPreview.d.ts.map +1 -0
- package/dist/core/src/editor/ui/DragPreview.js +32 -0
- package/dist/core/src/editor/ui/PerfectTree.d.ts +79 -0
- package/dist/core/src/editor/ui/PerfectTree.d.ts.map +1 -0
- package/dist/core/src/editor/ui/PerfectTree.js +857 -0
- package/dist/localization/src/LocalizeItemCommand.d.ts +8 -0
- package/dist/localization/src/LocalizeItemCommand.d.ts.map +1 -0
- package/dist/localization/src/LocalizeItemCommand.js +44 -0
- package/dist/localization/src/LocalizeItemDialog.d.ts +4 -0
- package/dist/localization/src/LocalizeItemDialog.d.ts.map +1 -0
- package/dist/localization/src/LocalizeItemDialog.js +126 -0
- package/dist/localization/src/LocalizeItemUtils.d.ts +17 -0
- package/dist/localization/src/LocalizeItemUtils.d.ts.map +1 -0
- package/dist/localization/src/LocalizeItemUtils.js +93 -0
- package/dist/localization/src/api/discovery.d.ts +36 -0
- package/dist/localization/src/api/discovery.d.ts.map +1 -0
- package/dist/localization/src/api/discovery.js +29 -0
- package/dist/localization/src/constants.d.ts +15 -0
- package/dist/localization/src/constants.d.ts.map +1 -0
- package/dist/localization/src/constants.js +21 -0
- package/dist/localization/src/hooks/useTranslationWizard.d.ts +6 -0
- package/dist/localization/src/hooks/useTranslationWizard.d.ts.map +1 -0
- package/dist/localization/src/hooks/useTranslationWizard.js +78 -0
- package/dist/localization/src/index.d.ts +69 -0
- package/dist/localization/src/index.d.ts.map +1 -0
- package/dist/localization/src/index.js +152 -0
- package/dist/localization/src/services/translationService.d.ts +102 -0
- package/dist/localization/src/services/translationService.d.ts.map +1 -0
- package/dist/localization/src/services/translationService.js +37 -0
- package/dist/localization/src/setup/LocalizationSetupStep.d.ts +3 -0
- package/dist/localization/src/setup/LocalizationSetupStep.d.ts.map +1 -0
- package/dist/localization/src/setup/LocalizationSetupStep.js +108 -0
- package/dist/localization/src/sidebar/TranslationSidebar.d.ts +2 -0
- package/dist/localization/src/sidebar/TranslationSidebar.d.ts.map +1 -0
- package/dist/localization/src/sidebar/TranslationSidebar.js +93 -0
- package/dist/localization/src/steps/MetadataInputStep.d.ts +4 -0
- package/dist/localization/src/steps/MetadataInputStep.d.ts.map +1 -0
- package/dist/localization/src/steps/MetadataInputStep.js +38 -0
- package/dist/localization/src/steps/ServiceLanguageSelectionStep.d.ts +3 -0
- package/dist/localization/src/steps/ServiceLanguageSelectionStep.d.ts.map +1 -0
- package/dist/localization/src/steps/ServiceLanguageSelectionStep.js +91 -0
- package/dist/localization/src/steps/SubitemDiscoveryStep.d.ts +3 -0
- package/dist/localization/src/steps/SubitemDiscoveryStep.d.ts.map +1 -0
- package/dist/localization/src/steps/SubitemDiscoveryStep.js +391 -0
- package/dist/localization/src/steps/index.d.ts +5 -0
- package/dist/localization/src/steps/index.d.ts.map +1 -0
- package/dist/localization/src/steps/index.js +4 -0
- package/dist/localization/src/steps/types.d.ts +68 -0
- package/dist/localization/src/steps/types.d.ts.map +1 -0
- package/dist/localization/src/steps/types.js +1 -0
- package/dist/localization/src/translation-center/BatchTranslationView.d.ts +7 -0
- package/dist/localization/src/translation-center/BatchTranslationView.d.ts.map +1 -0
- package/dist/localization/src/translation-center/BatchTranslationView.js +487 -0
- package/dist/localization/src/translation-center/RecentTranslations.d.ts +2 -0
- package/dist/localization/src/translation-center/RecentTranslations.d.ts.map +1 -0
- package/dist/localization/src/translation-center/RecentTranslations.js +199 -0
- package/dist/localization/src/translation-center/TranslationManagement.d.ts +2 -0
- package/dist/localization/src/translation-center/TranslationManagement.d.ts.map +1 -0
- package/dist/localization/src/translation-center/TranslationManagement.js +25 -0
- package/dist/localization/src/types.d.ts +18 -0
- package/dist/localization/src/types.d.ts.map +1 -0
- package/dist/localization/src/types.js +1 -0
- package/dist/localization/src/utils/createVersions.d.ts +14 -0
- package/dist/localization/src/utils/createVersions.d.ts.map +1 -0
- package/dist/localization/src/utils/createVersions.js +26 -0
- package/package.json +47 -0
- package/styles.css +1 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState, useMemo, useRef } from "react";
|
|
3
|
+
import { useRouter } from "next/navigation";
|
|
4
|
+
import { usePathname, useSearchParams } from "next/navigation";
|
|
5
|
+
import { useEditContext } from "@parhelia/core";
|
|
6
|
+
import { listBatches, } from "../services/translationService";
|
|
7
|
+
import { Button } from "@parhelia/core";
|
|
8
|
+
import { useDebouncedCallback } from "use-debounce";
|
|
9
|
+
export function RecentTranslations() {
|
|
10
|
+
const editContext = useEditContext();
|
|
11
|
+
const router = useRouter();
|
|
12
|
+
const pathname = usePathname();
|
|
13
|
+
const searchParams = useSearchParams();
|
|
14
|
+
const [batches, setBatches] = useState([]);
|
|
15
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
16
|
+
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
|
17
|
+
const [hasMore, setHasMore] = useState(true);
|
|
18
|
+
const [currentOffset, setCurrentOffset] = useState(0);
|
|
19
|
+
const debouncedReload = useDebouncedCallback(() => loadRecentBatches(0, false), 800);
|
|
20
|
+
const didInitialLoadRef = useRef(false);
|
|
21
|
+
const [filters, setFilters] = useState({
|
|
22
|
+
dateRange: "last30days",
|
|
23
|
+
status: "all",
|
|
24
|
+
});
|
|
25
|
+
const loadRecentBatches = async (offset = 0, append = false) => {
|
|
26
|
+
if (offset === 0) {
|
|
27
|
+
setIsLoading(true);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
setIsLoadingMore(true);
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const limit = 100;
|
|
34
|
+
const res = await listBatches(limit, offset);
|
|
35
|
+
const maybeData = res?.data ?? res;
|
|
36
|
+
const newBatches = Array.isArray(maybeData) ? maybeData : [];
|
|
37
|
+
if (append) {
|
|
38
|
+
setBatches(prev => {
|
|
39
|
+
const map = new Map();
|
|
40
|
+
for (const b of prev)
|
|
41
|
+
map.set(b.batchId, b);
|
|
42
|
+
for (const b of newBatches)
|
|
43
|
+
map.set(b.batchId, b);
|
|
44
|
+
return Array.from(map.values());
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// Deduplicate in case the API returns duplicates within a page
|
|
49
|
+
const map = new Map();
|
|
50
|
+
for (const b of newBatches)
|
|
51
|
+
map.set(b.batchId, b);
|
|
52
|
+
setBatches(Array.from(map.values()));
|
|
53
|
+
}
|
|
54
|
+
setHasMore(newBatches.length === limit);
|
|
55
|
+
setCurrentOffset(offset + limit);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error("Failed to load batches:", error);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
setIsLoading(false);
|
|
62
|
+
setIsLoadingMore(false);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const loadMore = () => {
|
|
66
|
+
if (!isLoadingMore && hasMore) {
|
|
67
|
+
loadRecentBatches(currentOffset, true);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
// Load initial data
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (didInitialLoadRef.current)
|
|
73
|
+
return;
|
|
74
|
+
didInitialLoadRef.current = true;
|
|
75
|
+
loadRecentBatches(0, false);
|
|
76
|
+
}, []);
|
|
77
|
+
// Listen for batch-related events to refresh the list
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
const removeSocketMessageListener = editContext?.addSocketMessageListener((message) => {
|
|
80
|
+
if (message.type === "batch-completed") {
|
|
81
|
+
debouncedReload();
|
|
82
|
+
}
|
|
83
|
+
if ((message.type === "translation-started" || message.type === "translation-finished" || message.type === "translation-error") && message.payload?.batchId) {
|
|
84
|
+
debouncedReload();
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
return () => {
|
|
88
|
+
if (removeSocketMessageListener) {
|
|
89
|
+
removeSocketMessageListener();
|
|
90
|
+
}
|
|
91
|
+
debouncedReload.cancel();
|
|
92
|
+
};
|
|
93
|
+
}, [editContext, debouncedReload]);
|
|
94
|
+
// Filter batches
|
|
95
|
+
const filteredBatches = useMemo(() => {
|
|
96
|
+
let filtered = [...batches];
|
|
97
|
+
const now = new Date();
|
|
98
|
+
const cutoffDate = new Date();
|
|
99
|
+
switch (filters.dateRange) {
|
|
100
|
+
case "today":
|
|
101
|
+
cutoffDate.setHours(0, 0, 0, 0);
|
|
102
|
+
break;
|
|
103
|
+
case "last7days":
|
|
104
|
+
cutoffDate.setDate(now.getDate() - 7);
|
|
105
|
+
break;
|
|
106
|
+
case "last30days":
|
|
107
|
+
cutoffDate.setDate(now.getDate() - 30);
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
filtered = filtered.filter(b => new Date(b.startedAtUtc || b.createdAtUtc || b.lastUpdatedUtc || new Date().toISOString()) >= cutoffDate);
|
|
111
|
+
if (filters.status !== "all") {
|
|
112
|
+
switch (filters.status) {
|
|
113
|
+
case "in-progress":
|
|
114
|
+
filtered = filtered.filter(b => b.status === "In Progress");
|
|
115
|
+
break;
|
|
116
|
+
case "completed":
|
|
117
|
+
filtered = filtered.filter(b => b.status === "Completed");
|
|
118
|
+
break;
|
|
119
|
+
case "errors":
|
|
120
|
+
filtered = filtered.filter(b => b.status === "Error");
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return filtered;
|
|
125
|
+
}, [batches, filters]);
|
|
126
|
+
// Group by date
|
|
127
|
+
const groupedBatches = useMemo(() => {
|
|
128
|
+
if (filteredBatches.length === 0)
|
|
129
|
+
return [];
|
|
130
|
+
// Deduplicate just in case state merging introduced any duplicates
|
|
131
|
+
const dedupMap = new Map();
|
|
132
|
+
for (const b of filteredBatches)
|
|
133
|
+
dedupMap.set(b.batchId, b);
|
|
134
|
+
const sorted = Array.from(dedupMap.values()).sort((a, b) => new Date(b.startedAtUtc || b.createdAtUtc || b.lastUpdatedUtc || '').getTime() -
|
|
135
|
+
new Date(a.startedAtUtc || a.createdAtUtc || a.lastUpdatedUtc || '').getTime());
|
|
136
|
+
const list = sorted.map(b => ({
|
|
137
|
+
id: b.batchId,
|
|
138
|
+
timestamp: b.startedAtUtc || b.createdAtUtc || b.lastUpdatedUtc || new Date().toISOString(),
|
|
139
|
+
info: b,
|
|
140
|
+
}));
|
|
141
|
+
const now = new Date();
|
|
142
|
+
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
143
|
+
const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);
|
|
144
|
+
const thisWeek = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
145
|
+
const dateGroups = [];
|
|
146
|
+
const todayBatches = [];
|
|
147
|
+
const yesterdayBatches = [];
|
|
148
|
+
const thisWeekBatches = [];
|
|
149
|
+
const olderBatches = [];
|
|
150
|
+
for (const b of list) {
|
|
151
|
+
const d = new Date(b.timestamp);
|
|
152
|
+
const day = new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
153
|
+
if (day.getTime() === today.getTime())
|
|
154
|
+
todayBatches.push(b);
|
|
155
|
+
else if (day.getTime() === yesterday.getTime())
|
|
156
|
+
yesterdayBatches.push(b);
|
|
157
|
+
else if (day >= thisWeek)
|
|
158
|
+
thisWeekBatches.push(b);
|
|
159
|
+
else
|
|
160
|
+
olderBatches.push(b);
|
|
161
|
+
}
|
|
162
|
+
if (todayBatches.length)
|
|
163
|
+
dateGroups.push({ label: "Today", batches: todayBatches });
|
|
164
|
+
if (yesterdayBatches.length)
|
|
165
|
+
dateGroups.push({ label: "Yesterday", batches: yesterdayBatches });
|
|
166
|
+
if (thisWeekBatches.length)
|
|
167
|
+
dateGroups.push({ label: "This Week", batches: thisWeekBatches });
|
|
168
|
+
if (olderBatches.length)
|
|
169
|
+
dateGroups.push({ label: "Older", batches: olderBatches });
|
|
170
|
+
return dateGroups;
|
|
171
|
+
}, [filteredBatches]);
|
|
172
|
+
const navigateToBatch = (batchId) => {
|
|
173
|
+
const current = new URLSearchParams(Array.from(searchParams.entries()));
|
|
174
|
+
current.set("batchId", batchId);
|
|
175
|
+
router.push(`${pathname}?${current.toString()}`, { scroll: false });
|
|
176
|
+
};
|
|
177
|
+
const totalBatches = groupedBatches.reduce((sum, group) => sum + group.batches.length, 0);
|
|
178
|
+
return (_jsxs("div", { className: "flex h-full flex-col min-h-0", children: [_jsxs("div", { className: "border-b p-4 flex-shrink-0", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-xl font-semibold", children: "Recent Translations" }), _jsx("p", { className: "text-sm text-gray-600 mt-1", children: "View and monitor translation jobs across all items" })] }), _jsx("div", { className: "flex gap-2", children: _jsxs(Button, { size: "sm", onClick: () => loadRecentBatches(0, false), disabled: isLoading, children: [_jsx("i", { className: `pi pi-refresh ${isLoading ? 'pi-spin' : ''}` }), "Refresh"] }) })] }), _jsxs("div", { className: "flex flex-wrap gap-4 items-center", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("label", { className: "text-sm font-medium text-gray-700", children: "Date Range:" }), _jsxs("select", { value: filters.dateRange, onChange: (e) => setFilters(prev => ({ ...prev, dateRange: e.target.value })), className: "px-3 py-1 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500", children: [_jsx("option", { value: "today", children: "Today" }), _jsx("option", { value: "last7days", children: "Last 7 Days" }), _jsx("option", { value: "last30days", children: "Last 30 Days" })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("label", { className: "text-sm font-medium text-gray-700", children: "Status:" }), _jsxs("select", { value: filters.status, onChange: (e) => setFilters(prev => ({ ...prev, status: e.target.value })), className: "px-3 py-1 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500", children: [_jsx("option", { value: "all", children: "All Status" }), _jsx("option", { value: "in-progress", children: "In Progress" }), _jsx("option", { value: "completed", children: "Completed" }), _jsx("option", { value: "errors", children: "Errors Only" })] })] }), (filters.dateRange !== "last30days" || filters.status !== "all") && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => setFilters({ dateRange: "last30days", status: "all" }), children: [_jsx("i", { className: "pi pi-times" }), "Clear Filters"] }))] }), _jsxs("div", { className: "mt-3 text-sm text-gray-600", children: ["Showing ", totalBatches, " batch", totalBatches !== 1 ? 'es' : '', batches.length !== totalBatches && (_jsxs("span", { children: [" (filtered from ", batches.length, " total batches)"] }))] })] }), _jsx("div", { className: "flex-1 overflow-auto p-4 min-h-0", 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-gray-500", children: [_jsx("i", { className: "pi pi-spin pi-spinner" }), "Loading recent translations..."] }) })) : groupedBatches.length === 0 ? (_jsx("div", { className: "flex items-center justify-center h-32", children: _jsxs("div", { className: "text-center text-gray-500", children: [_jsx("i", { className: "pi pi-language text-2xl block mb-2" }), _jsx("p", { children: "No translations found" }), _jsx("p", { className: "text-sm", children: filteredBatches.length !== batches.length
|
|
179
|
+
? "Try adjusting your filters or start a translation to see it appear here"
|
|
180
|
+
: "Start a translation to see it appear here" })] }) })) : (_jsxs("div", { className: "space-y-6", children: [groupedBatches.map((dateGroup) => (_jsxs("div", { children: [_jsxs("h2", { className: "text-lg font-semibold text-gray-800 mb-3 border-b pb-1", children: [dateGroup.label, _jsxs("span", { className: "ml-2 text-sm font-normal text-gray-500", children: ["(", dateGroup.batches.length, " batch", dateGroup.batches.length !== 1 ? 'es' : '', ")"] })] }), _jsx("div", { className: "space-y-3", children: dateGroup.batches.map((b) => {
|
|
181
|
+
const batchDate = new Date(b.timestamp);
|
|
182
|
+
const now = new Date();
|
|
183
|
+
const isToday = batchDate.toDateString() === now.toDateString();
|
|
184
|
+
const timeDisplay = isToday
|
|
185
|
+
? batchDate.toLocaleTimeString()
|
|
186
|
+
: batchDate.toLocaleDateString() + " " + batchDate.toLocaleTimeString();
|
|
187
|
+
const info = b.info;
|
|
188
|
+
const totalJobs = info?.expectedJobs ?? 0;
|
|
189
|
+
const itemsCount = typeof info?.itemsCount === 'number' ? info.itemsCount : undefined;
|
|
190
|
+
const languagesCsv = info?.languages;
|
|
191
|
+
const languages = languagesCsv ? languagesCsv.split(',') : [];
|
|
192
|
+
const completedJobs = info?.completedJobs ?? 0;
|
|
193
|
+
const anyError = (info?.errorJobs ?? 0) > 0;
|
|
194
|
+
const anyInProgress = info?.status === "In Progress";
|
|
195
|
+
return (_jsx("div", { className: "border rounded-lg", children: _jsx("button", { className: "w-full bg-gray-50 px-4 py-3 hover:bg-gray-100 transition-colors text-left", onClick: () => navigateToBatch(b.id), title: "View batch details", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "text-left", children: [_jsx("div", { className: "font-medium text-gray-900", children: `Translation Batch - ${timeDisplay}` }), _jsxs("div", { className: "text-sm text-gray-600", children: [totalJobs, " translations", typeof itemsCount === 'number' && (_jsxs("span", { children: [" \u2022 ", itemsCount, " items"] })), languages.length ? (_jsxs("span", { children: [" \u2022 ", languages.join(", ")] })) : null, _jsxs("span", { className: "ml-2 text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded-full", children: ["Batch ID: ", b.id] }), totalJobs > 0 && (_jsxs("span", { className: "ml-2 text-xs text-gray-500", children: ["(", completedJobs, "/", totalJobs, " completed", info?.errorJobs ? `, ${info.errorJobs} errors` : '', ")"] }))] }), _jsxs("div", { className: "mt-1 flex flex-wrap gap-2 items-center text-xs", children: [info?.status && (_jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 font-medium ${info.status === 'Completed' ? 'bg-green-100 text-green-700' :
|
|
196
|
+
info.status === 'In Progress' ? 'bg-blue-100 text-blue-700' :
|
|
197
|
+
info.status === 'Error' ? 'bg-red-100 text-red-700' : 'bg-gray-100 text-gray-700'}`, children: info.status })), info?.provider && (_jsxs("span", { className: "text-gray-700", children: ["Provider: ", _jsx("span", { className: "font-medium", children: info.provider })] })), info?.initiatedByUser && (_jsxs("span", { className: "text-gray-700", children: ["By: ", _jsx("span", { className: "font-medium", children: info.initiatedByUser })] })), info?.lastUpdatedUtc && (_jsxs("span", { className: "text-gray-500", children: ["Updated: ", new Date(info.lastUpdatedUtc).toLocaleString()] }))] })] }), _jsxs("div", { className: "flex gap-2", children: [anyInProgress && (_jsx("span", { className: "rounded-full bg-blue-100 px-3 py-1 text-xs font-medium text-blue-700", children: "In Progress" })), anyError && (_jsx("span", { className: "rounded-full bg-red-100 px-3 py-1 text-xs font-medium text-red-700", children: "Error" })), !anyInProgress && !anyError && (_jsx("span", { className: "rounded-full bg-green-100 px-3 py-1 text-xs font-medium text-green-700", children: "Completed" }))] })] }) }) }, b.id));
|
|
198
|
+
}) })] }, dateGroup.label))), hasMore && (_jsx("div", { className: "flex justify-center pt-4", children: _jsx(Button, { variant: "outline", onClick: loadMore, disabled: isLoadingMore, children: isLoadingMore ? (_jsxs(_Fragment, { children: [_jsx("i", { className: "pi pi-spin pi-spinner mr-2" }), "Loading more..."] })) : (_jsxs(_Fragment, { children: [_jsx("i", { className: "pi pi-chevron-down mr-2" }), "Load More Batches"] })) }) }))] })) })] }));
|
|
199
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TranslationManagement.d.ts","sourceRoot":"","sources":["../../../../src/translation-center/TranslationManagement.tsx"],"names":[],"mappings":"AAKA,wBAAgB,qBAAqB,4CA4CpC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRouter } from "next/navigation";
|
|
3
|
+
import { usePathname, useSearchParams } from "next/navigation";
|
|
4
|
+
import { useEditContext } from "@parhelia/core";
|
|
5
|
+
import { BatchTranslationView } from "./BatchTranslationView";
|
|
6
|
+
export function TranslationManagement() {
|
|
7
|
+
const editContext = useEditContext();
|
|
8
|
+
const config = editContext?.configuration;
|
|
9
|
+
const searchParams = useSearchParams();
|
|
10
|
+
const batchId = searchParams.get("batchId");
|
|
11
|
+
const router = useRouter();
|
|
12
|
+
const pathname = usePathname();
|
|
13
|
+
// Get the Recent Translations panel content (since it's the only one)
|
|
14
|
+
const recentTranslationsPanel = config?.translationCenter?.groups
|
|
15
|
+
?.flatMap((x) => x.panels)
|
|
16
|
+
?.find((panel) => panel.id === "recent-translations");
|
|
17
|
+
if (!config) {
|
|
18
|
+
return (_jsx("div", { className: "flex h-full flex-col items-center justify-center", children: "Loading..." }));
|
|
19
|
+
}
|
|
20
|
+
return (_jsx("div", { className: "absolute inset-0 flex flex-col", children: batchId ? (_jsx(BatchTranslationView, { batchId: batchId, onBack: () => {
|
|
21
|
+
const current = new URLSearchParams(Array.from(searchParams.entries()));
|
|
22
|
+
current.delete("batchId");
|
|
23
|
+
router.push(`${pathname}?${current.toString()}`, { scroll: false });
|
|
24
|
+
} })) : 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-gray-500", children: [_jsx("i", { className: "pi pi-language mb-4 text-4xl" }), _jsx("p", { children: "Recent translations not available" })] })) }));
|
|
25
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ControlCenterPanel } from "@parhelia/core";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
export type TranslationStatus = {
|
|
4
|
+
itemId: string;
|
|
5
|
+
targetLanguage: string;
|
|
6
|
+
sourceLanguage: string;
|
|
7
|
+
status: string;
|
|
8
|
+
timestamp: string;
|
|
9
|
+
message?: string;
|
|
10
|
+
};
|
|
11
|
+
export type translationCenter = {
|
|
12
|
+
groups: {
|
|
13
|
+
title: string;
|
|
14
|
+
icon: ReactNode;
|
|
15
|
+
panels: ControlCenterPanel[];
|
|
16
|
+
}[];
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,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,kBAAkB,EAAE,CAAC;KAC9B,EAAE,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EditContextType } from "@parhelia/core";
|
|
2
|
+
import { TranslationWizardData, TranslationDialogResult } from "../steps/types";
|
|
3
|
+
export type ItemVersionDescriptor = {
|
|
4
|
+
id: string;
|
|
5
|
+
version?: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function createVersionsOnlyAndClose(params: {
|
|
8
|
+
items: ItemVersionDescriptor[];
|
|
9
|
+
targetLanguages: string[];
|
|
10
|
+
editContext: EditContextType;
|
|
11
|
+
data: TranslationWizardData;
|
|
12
|
+
requestClose: (result: TranslationDialogResult | null) => void;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=createVersions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createVersions.d.ts","sourceRoot":"","sources":["../../../../src/utils/createVersions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAGhF,MAAM,MAAM,qBAAqB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE;IACN,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,qBAAqB,CAAC;IAC5B,YAAY,EAAE,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI,KAAK,IAAI,CAAC;CAChE,GACA,OAAO,CAAC,IAAI,CAAC,CAyBf"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createVersion as createVersionEdit, createVersionsBatch as createVersionsBatchEdit } from "@parhelia/core";
|
|
2
|
+
export async function createVersionsOnlyAndClose(params) {
|
|
3
|
+
const { items, targetLanguages, editContext, data, requestClose } = params;
|
|
4
|
+
try {
|
|
5
|
+
if (items.length === 1 && targetLanguages.length === 1) {
|
|
6
|
+
const item = items[0];
|
|
7
|
+
await createVersionEdit({ id: item.id, language: targetLanguages[0], version: item.version || 0 }, editContext.sessionId);
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
const descriptors = items.flatMap(it => targetLanguages.map(lang => ({ id: it.id, language: lang, version: it.version || 0 })));
|
|
11
|
+
await createVersionsBatchEdit(descriptors, editContext.sessionId);
|
|
12
|
+
}
|
|
13
|
+
editContext?.showToast?.("Versions created");
|
|
14
|
+
const result = {
|
|
15
|
+
translationProvider: data.translationProvider,
|
|
16
|
+
targetLanguages: data.targetLanguages,
|
|
17
|
+
includeSubitems: data.includeSubitems,
|
|
18
|
+
discoveredItems: data.discoveredItems,
|
|
19
|
+
};
|
|
20
|
+
requestClose(result);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
console.error("Create versions failed", e);
|
|
24
|
+
editContext?.showToast?.("Failed to create versions");
|
|
25
|
+
}
|
|
26
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@parhelia/localization",
|
|
3
|
+
"version": "0.1.10745",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./styles.css": "./styles.css"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist/",
|
|
20
|
+
"styles.css",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -p tsconfig.build.json",
|
|
26
|
+
"lint": "eslint . --max-warnings 0",
|
|
27
|
+
"generate:component": "turbo gen react-component",
|
|
28
|
+
"check-types": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@repo/eslint-config": "*",
|
|
32
|
+
"@repo/typescript-config": "*",
|
|
33
|
+
"@turbo/gen": "^2.4.4",
|
|
34
|
+
"@types/node": "^22.13.9",
|
|
35
|
+
"@types/react": "19.0.10",
|
|
36
|
+
"@types/react-dom": "19.0.4",
|
|
37
|
+
"eslint": "^9.22.0",
|
|
38
|
+
"typescript": "5.8.2"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@tailwindcss/postcss": "^4.0.14",
|
|
42
|
+
"postcss": "^8.5.3",
|
|
43
|
+
"react": "^19.0.0",
|
|
44
|
+
"react-dom": "^19.0.0",
|
|
45
|
+
"tailwindcss": "^4.0.14"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/styles.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/* Localization package styles */
|