@parhelia/localization 0.1.12788 → 0.1.12790

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 (57) hide show
  1. package/dist/LocalizeItemDialog.d.ts.map +1 -1
  2. package/dist/LocalizeItemDialog.js +92 -34
  3. package/dist/LocalizeItemUtils.d.ts +1 -2
  4. package/dist/LocalizeItemUtils.d.ts.map +1 -1
  5. package/dist/LocalizeItemUtils.js +44 -12
  6. package/dist/api/discovery.d.ts +25 -0
  7. package/dist/api/discovery.d.ts.map +1 -1
  8. package/dist/api/discovery.js +87 -0
  9. package/dist/index.d.ts +8 -17
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +32 -32
  12. package/dist/services/translationService.d.ts +40 -9
  13. package/dist/services/translationService.d.ts.map +1 -1
  14. package/dist/services/translationService.js +30 -4
  15. package/dist/settings/TranslationServicesPanel.d.ts.map +1 -1
  16. package/dist/settings/TranslationServicesPanel.js +18 -36
  17. package/dist/sidebar/TranslationSidebar.d.ts.map +1 -1
  18. package/dist/sidebar/TranslationSidebar.js +4 -1
  19. package/dist/steps/ItemSelectionStep.d.ts +3 -0
  20. package/dist/steps/ItemSelectionStep.d.ts.map +1 -0
  21. package/dist/steps/ItemSelectionStep.js +23 -0
  22. package/dist/steps/ItemSelectionTree.d.ts +13 -0
  23. package/dist/steps/ItemSelectionTree.d.ts.map +1 -0
  24. package/dist/steps/ItemSelectionTree.js +326 -0
  25. package/dist/steps/MetadataInputStep.d.ts.map +1 -1
  26. package/dist/steps/MetadataInputStep.js +8 -1
  27. package/dist/steps/PromptCustomizationStep.d.ts +1 -1
  28. package/dist/steps/PromptCustomizationStep.d.ts.map +1 -1
  29. package/dist/steps/PromptCustomizationStep.js +161 -56
  30. package/dist/steps/ServiceLanguageSelectionStep.d.ts +6 -1
  31. package/dist/steps/ServiceLanguageSelectionStep.d.ts.map +1 -1
  32. package/dist/steps/ServiceLanguageSelectionStep.js +53 -163
  33. package/dist/steps/WizardStepShell.d.ts +17 -0
  34. package/dist/steps/WizardStepShell.d.ts.map +1 -0
  35. package/dist/steps/WizardStepShell.js +11 -0
  36. package/dist/steps/index.d.ts +1 -0
  37. package/dist/steps/index.d.ts.map +1 -1
  38. package/dist/steps/index.js +1 -0
  39. package/dist/steps/types.d.ts +17 -1
  40. package/dist/steps/types.d.ts.map +1 -1
  41. package/dist/translation-center/TranslationBatches.d.ts +2 -0
  42. package/dist/translation-center/TranslationBatches.d.ts.map +1 -0
  43. package/dist/translation-center/TranslationBatches.js +995 -0
  44. package/dist/translation-center/TranslationManagement.d.ts.map +1 -1
  45. package/dist/translation-center/TranslationManagement.js +22 -14
  46. package/dist/translation-center/TranslationsTitlebar.d.ts +7 -0
  47. package/dist/translation-center/TranslationsTitlebar.d.ts.map +1 -0
  48. package/dist/translation-center/TranslationsTitlebar.js +16 -0
  49. package/dist/types.d.ts +1 -0
  50. package/dist/types.d.ts.map +1 -1
  51. package/package.json +1 -1
  52. package/dist/translation-center/BatchTranslationView.d.ts +0 -8
  53. package/dist/translation-center/BatchTranslationView.d.ts.map +0 -1
  54. package/dist/translation-center/BatchTranslationView.js +0 -870
  55. package/dist/translation-center/RecentTranslations.d.ts +0 -2
  56. package/dist/translation-center/RecentTranslations.d.ts.map +0 -1
  57. package/dist/translation-center/RecentTranslations.js +0 -309
@@ -1,2 +0,0 @@
1
- export declare function RecentTranslations(): import("react/jsx-runtime").JSX.Element;
2
- //# sourceMappingURL=RecentTranslations.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RecentTranslations.d.ts","sourceRoot":"","sources":["../../src/translation-center/RecentTranslations.tsx"],"names":[],"mappings":"AAwEA,wBAAgB,kBAAkB,4CAyhBjC"}
@@ -1,309 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useState, useMemo } from "react";
3
- import React from "react";
4
- import { Button, Select, useEditContext, usePathname, useRouter, useSearchParams, } from "@parhelia/core";
5
- import { listBatches, getTranslationProviders, } from "../services/translationService";
6
- import { useDebouncedCallback } from "use-debounce";
7
- import { RefreshCw, X, ChevronDown, Languages, Loader2 } from "lucide-react";
8
- // Wrappers for lucide-react icons to work with React 19
9
- const RefreshIcon = (props) => React.createElement(RefreshCw, props);
10
- const XIcon = (props) => React.createElement(X, props);
11
- const ChevronDownIcon = (props) => React.createElement(ChevronDown, props);
12
- const LanguagesIcon = (props) => React.createElement(Languages, props);
13
- const LoaderIcon = (props) => React.createElement(Loader2, props);
14
- const DATE_RANGE_OPTIONS = [
15
- { value: "lastHour", label: "Last Hour" },
16
- { value: "last24hours", label: "Last 24 Hours" },
17
- { value: "today", label: "Today" },
18
- { value: "last7days", label: "Last 7 Days" },
19
- { value: "last30days", label: "Last 30 Days" },
20
- ];
21
- const STATUS_OPTIONS = [
22
- { value: "all", label: "All Status" },
23
- { value: "in-progress", label: "In Progress" },
24
- { value: "completed", label: "Completed" },
25
- { value: "errors", label: "Errors Only" },
26
- ];
27
- export function RecentTranslations() {
28
- const editContext = useEditContext();
29
- const router = useRouter();
30
- const pathname = usePathname();
31
- const searchParams = useSearchParams();
32
- const [batches, setBatches] = useState([]);
33
- const [providers, setProviders] = useState([]);
34
- const [isLoading, setIsLoading] = useState(false);
35
- const [isLoadingMore, setIsLoadingMore] = useState(false);
36
- const [hasMore, setHasMore] = useState(true);
37
- const [currentOffset, setCurrentOffset] = useState(0);
38
- const debouncedReload = useDebouncedCallback(() => loadRecentBatches(0, false), 800);
39
- const currentUserName = editContext?.user?.name || "all";
40
- const isLimitedPreviewUser = editContext?.user?.isLimitedPreviewUser ?? false;
41
- const [filters, setFilters] = useState({
42
- dateRange: "last30days",
43
- status: "all",
44
- user: currentUserName,
45
- provider: "all",
46
- targetLanguage: "all",
47
- });
48
- // Enforce current user filter for limited preview users
49
- useEffect(() => {
50
- if (isLimitedPreviewUser && currentUserName !== "all" && filters.user !== currentUserName) {
51
- setFilters(prev => ({ ...prev, user: currentUserName }));
52
- }
53
- }, [isLimitedPreviewUser, currentUserName, filters.user]);
54
- const loadRecentBatches = async (offset = 0, append = false) => {
55
- if (offset === 0) {
56
- setIsLoading(true);
57
- }
58
- else {
59
- setIsLoadingMore(true);
60
- }
61
- try {
62
- const limit = 100;
63
- const res = await listBatches(limit, offset);
64
- const maybeData = res?.data ?? res;
65
- const newBatches = Array.isArray(maybeData) ? maybeData : [];
66
- if (append) {
67
- setBatches(prev => {
68
- const map = new Map();
69
- for (const b of prev)
70
- map.set(b.batchId, b);
71
- for (const b of newBatches)
72
- map.set(b.batchId, b);
73
- return Array.from(map.values());
74
- });
75
- }
76
- else {
77
- // Deduplicate in case the API returns duplicates within a page
78
- const map = new Map();
79
- for (const b of newBatches)
80
- map.set(b.batchId, b);
81
- setBatches(Array.from(map.values()));
82
- }
83
- setHasMore(newBatches.length === limit);
84
- setCurrentOffset(offset + limit);
85
- }
86
- catch (error) {
87
- console.error("Failed to load batches:", error);
88
- }
89
- finally {
90
- setIsLoading(false);
91
- setIsLoadingMore(false);
92
- }
93
- };
94
- const loadMore = () => {
95
- if (!isLoadingMore && hasMore) {
96
- loadRecentBatches(currentOffset, true);
97
- }
98
- };
99
- // Load providers
100
- useEffect(() => {
101
- const loadProviders = async () => {
102
- try {
103
- const res = await getTranslationProviders();
104
- const providerData = (res?.data ?? res ?? []);
105
- setProviders(providerData);
106
- }
107
- catch (error) {
108
- console.error("Failed to load translation providers:", error);
109
- }
110
- };
111
- loadProviders();
112
- }, []);
113
- // Load initial data
114
- useEffect(() => {
115
- loadRecentBatches(0, false);
116
- }, []);
117
- // Listen for batch-related events to refresh the list
118
- useEffect(() => {
119
- const removeSocketMessageListener = editContext?.addSocketMessageListener((message) => {
120
- if (message.type === "batch-completed") {
121
- debouncedReload();
122
- }
123
- if ((message.type === "translation-started" || message.type === "translation-finished" || message.type === "translation-error") && message.payload?.batchId) {
124
- debouncedReload();
125
- }
126
- });
127
- return () => {
128
- if (removeSocketMessageListener) {
129
- removeSocketMessageListener();
130
- }
131
- debouncedReload.cancel();
132
- };
133
- }, [editContext, debouncedReload]);
134
- // Extract unique users from batches
135
- const uniqueUsers = useMemo(() => {
136
- const users = new Set();
137
- batches.forEach(b => {
138
- if (b.initiatedByUser) {
139
- users.add(b.initiatedByUser);
140
- }
141
- });
142
- return Array.from(users).sort();
143
- }, [batches]);
144
- // Extract unique languages from batches
145
- const uniqueLanguages = useMemo(() => {
146
- const languages = new Set();
147
- batches.forEach(b => {
148
- const languagesCsv = b?.languages;
149
- if (languagesCsv) {
150
- languagesCsv.split(',').forEach(lang => {
151
- const trimmed = lang.trim();
152
- if (trimmed) {
153
- languages.add(trimmed);
154
- }
155
- });
156
- }
157
- });
158
- return Array.from(languages).sort();
159
- }, [batches]);
160
- // Filter batches
161
- const filteredBatches = useMemo(() => {
162
- let filtered = [...batches];
163
- const now = new Date();
164
- const cutoffDate = new Date();
165
- switch (filters.dateRange) {
166
- case "today":
167
- cutoffDate.setHours(0, 0, 0, 0);
168
- break;
169
- case "lastHour":
170
- cutoffDate.setTime(now.getTime() - 60 * 60 * 1000);
171
- break;
172
- case "last24hours":
173
- cutoffDate.setTime(now.getTime() - 24 * 60 * 60 * 1000);
174
- break;
175
- case "last7days":
176
- cutoffDate.setDate(now.getDate() - 7);
177
- break;
178
- case "last30days":
179
- cutoffDate.setDate(now.getDate() - 30);
180
- break;
181
- }
182
- filtered = filtered.filter(b => new Date(b.startedAtUtc || b.createdAtUtc || b.lastUpdatedUtc || new Date().toISOString()) >= cutoffDate);
183
- if (filters.status !== "all") {
184
- switch (filters.status) {
185
- case "in-progress":
186
- filtered = filtered.filter(b => b.status === "In Progress");
187
- break;
188
- case "completed":
189
- filtered = filtered.filter(b => b.status === "Completed");
190
- break;
191
- case "errors":
192
- filtered = filtered.filter(b => b.status === "Error");
193
- break;
194
- }
195
- }
196
- // Always filter by current user for limited preview users
197
- const userFilter = isLimitedPreviewUser ? currentUserName : filters.user;
198
- if (userFilter !== "all") {
199
- filtered = filtered.filter(b => b.initiatedByUser === userFilter);
200
- }
201
- if (filters.provider !== "all") {
202
- filtered = filtered.filter(b => b.provider === filters.provider);
203
- }
204
- if (filters.targetLanguage !== "all") {
205
- filtered = filtered.filter(b => {
206
- const languagesCsv = b?.languages;
207
- if (!languagesCsv)
208
- return false;
209
- const languages = languagesCsv.split(',').map(lang => lang.trim());
210
- return languages.includes(filters.targetLanguage);
211
- });
212
- }
213
- return filtered;
214
- }, [batches, filters, isLimitedPreviewUser, currentUserName]);
215
- // Group by date
216
- const groupedBatches = useMemo(() => {
217
- if (filteredBatches.length === 0)
218
- return [];
219
- // Deduplicate just in case state merging introduced any duplicates
220
- const dedupMap = new Map();
221
- for (const b of filteredBatches)
222
- dedupMap.set(b.batchId, b);
223
- const sorted = Array.from(dedupMap.values()).sort((a, b) => new Date(b.startedAtUtc || b.createdAtUtc || b.lastUpdatedUtc || '').getTime() -
224
- new Date(a.startedAtUtc || a.createdAtUtc || a.lastUpdatedUtc || '').getTime());
225
- const list = sorted.map(b => ({
226
- id: b.batchId,
227
- timestamp: b.startedAtUtc || b.createdAtUtc || b.lastUpdatedUtc || new Date().toISOString(),
228
- info: b,
229
- }));
230
- const now = new Date();
231
- const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
232
- const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);
233
- const thisWeek = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
234
- const dateGroups = [];
235
- const todayBatches = [];
236
- const yesterdayBatches = [];
237
- const thisWeekBatches = [];
238
- const olderBatches = [];
239
- for (const b of list) {
240
- const d = new Date(b.timestamp);
241
- const day = new Date(d.getFullYear(), d.getMonth(), d.getDate());
242
- if (day.getTime() === today.getTime())
243
- todayBatches.push(b);
244
- else if (day.getTime() === yesterday.getTime())
245
- yesterdayBatches.push(b);
246
- else if (day >= thisWeek)
247
- thisWeekBatches.push(b);
248
- else
249
- olderBatches.push(b);
250
- }
251
- if (todayBatches.length)
252
- dateGroups.push({ label: "Today", batches: todayBatches });
253
- if (yesterdayBatches.length)
254
- dateGroups.push({ label: "Yesterday", batches: yesterdayBatches });
255
- if (thisWeekBatches.length)
256
- dateGroups.push({ label: "This Week", batches: thisWeekBatches });
257
- if (olderBatches.length)
258
- dateGroups.push({ label: "Older", batches: olderBatches });
259
- return dateGroups;
260
- }, [filteredBatches]);
261
- const navigateToBatch = (batchId) => {
262
- const current = new URLSearchParams(searchParams.toString());
263
- current.set("batchId", batchId);
264
- router.push(`${pathname}?${current.toString()}`, { scroll: false });
265
- };
266
- const totalBatches = groupedBatches.reduce((sum, group) => sum + group.batches.length, 0);
267
- const isMobile = editContext?.isMobile ?? false;
268
- return (_jsxs("div", { className: "flex h-full flex-col min-h-0 bg-gray-5", "data-testid": "recent-translations", children: [_jsxs("div", { className: "shrink-0 border-b border-gray-3 bg-background p-4 md:p-6", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-xl font-semibold text-(--color-dark)", children: "Recent Translations" }), _jsx("p", { className: "text-sm text-gray-2 mt-1", children: "View and monitor translation jobs across all items" })] }), _jsx("div", { className: "flex gap-2", children: _jsxs(Button, { size: "sm", variant: "outline", onClick: () => loadRecentBatches(0, false), disabled: isLoading, className: "md:w-auto w-8 h-8 md:h-8 p-0 md:px-3", children: [_jsx(RefreshIcon, { className: `h-4 w-4 ${isLoading ? 'animate-spin' : ''}` }), _jsx("span", { className: "hidden md:inline", children: "Refresh" })] }) })] }), _jsxs("div", { className: "flex flex-wrap gap-4 items-center", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-medium text-(--color-gray-1)", children: "Date Range:" }), _jsx(Select, { className: "w-40", options: DATE_RANGE_OPTIONS, value: filters.dateRange, onValueChange: (value) => setFilters((prev) => ({ ...prev, dateRange: value })), placeholder: "Select date range" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-medium text-(--color-gray-1)", children: "Status:" }), _jsx(Select, { className: "w-36", options: STATUS_OPTIONS, value: filters.status, onValueChange: (value) => setFilters((prev) => ({ ...prev, status: value })), placeholder: "Select status" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-medium text-(--color-gray-1)", children: "User:" }), _jsx(Select, { className: "w-44", options: [
269
- { value: "all", label: "All Users" },
270
- ...(currentUserName !== "all"
271
- ? [{ value: currentUserName, label: `${currentUserName} (You)` }]
272
- : []),
273
- ...uniqueUsers
274
- .filter((u) => u !== currentUserName)
275
- .map((u) => ({ value: u, label: u })),
276
- ], value: isLimitedPreviewUser ? currentUserName : filters.user, onValueChange: (value) => setFilters((prev) => ({ ...prev, user: value })), disabled: isLimitedPreviewUser, placeholder: "Select user" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-medium text-(--color-gray-1)", children: "Provider:" }), _jsx(Select, { className: "w-44", options: [
277
- { value: "all", label: "All Providers" },
278
- ...providers.map((p) => ({
279
- value: p.name,
280
- label: p.displayName || p.name,
281
- })),
282
- ], value: filters.provider, onValueChange: (value) => setFilters((prev) => ({ ...prev, provider: value })), placeholder: "Select provider" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-medium text-(--color-gray-1)", children: "Target Language:" }), _jsx(Select, { className: "w-44", options: [
283
- { value: "all", label: "All Languages" },
284
- ...uniqueLanguages.map((lang) => ({
285
- value: lang,
286
- label: lang,
287
- })),
288
- ], value: filters.targetLanguage, onValueChange: (value) => setFilters((prev) => ({ ...prev, targetLanguage: value })), placeholder: "Select language" })] }), (filters.dateRange !== "last30days" || filters.status !== "all" || filters.user !== currentUserName || filters.provider !== "all" || filters.targetLanguage !== "all") && (_jsxs(Button, { size: "sm", variant: "ghost", onClick: () => setFilters({ dateRange: "last30days", status: "all", user: currentUserName, provider: "all", targetLanguage: "all" }), children: [_jsx("i", { className: "pi pi-times" }), "Clear Filters"] }))] }), _jsxs("div", { className: "mt-3 text-xs text-gray-2", 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 md:p-6 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-2", children: [_jsx(LoaderIcon, { className: "h-5 w-5 animate-spin text-theme-secondary" }), "Loading recent translations..."] }) })) : groupedBatches.length === 0 ? (_jsx("div", { className: "flex items-center justify-center h-32", children: _jsxs("div", { className: "text-center text-gray-2", children: [_jsx(LanguagesIcon, { className: "h-8 w-8 block mx-auto mb-2 text-gray-3" }), _jsx("p", { className: "font-medium text-(--color-gray-1)", children: "No translations found" }), _jsx("p", { className: "text-sm mt-1", children: filteredBatches.length !== batches.length
289
- ? "Try adjusting your filters or start a translation to see it appear here"
290
- : "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-(--color-dark) mb-3 border-b border-gray-3 pb-2", children: [dateGroup.label, _jsxs("span", { className: "ml-2 text-sm font-normal text-gray-2", children: ["(", dateGroup.batches.length, " batch", dateGroup.batches.length !== 1 ? 'es' : '', ")"] })] }), _jsx("div", { className: "space-y-3", children: dateGroup.batches.map((b) => {
291
- const batchDate = new Date(b.timestamp);
292
- const now = new Date();
293
- const isToday = batchDate.toDateString() === now.toDateString();
294
- const timeDisplay = isToday
295
- ? batchDate.toLocaleTimeString()
296
- : batchDate.toLocaleDateString() + " " + batchDate.toLocaleTimeString();
297
- const info = b.info;
298
- const totalJobs = info?.expectedJobs ?? 0;
299
- const itemsCount = typeof info?.itemsCount === 'number' ? info.itemsCount : undefined;
300
- const languagesCsv = info?.languages;
301
- const languages = languagesCsv ? languagesCsv.split(',') : [];
302
- const completedJobs = info?.completedJobs ?? 0;
303
- const anyError = (info?.errorJobs ?? 0) > 0;
304
- const anyInProgress = info?.status === "In Progress";
305
- return (_jsx("div", { className: "border border-gray-3 rounded-lg bg-background shadow-sm overflow-hidden transition-shadow hover:shadow-md", children: _jsx("button", { className: "w-full px-4 py-3 md:px-6 md:py-4 hover:bg-gray-5 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-(--color-dark)", children: `Translation Batch - ${timeDisplay}` }), _jsxs("div", { className: "text-sm text-gray-2 mt-1 flex flex-wrap items-center gap-x-2", children: [_jsxs("span", { className: "font-medium text-(--color-gray-1)", children: [totalJobs, " translations"] }), typeof itemsCount === 'number' && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-gray-3", children: "\u2022" }), _jsxs("span", { children: [itemsCount, " items"] })] })), languages.length ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-gray-3", children: "\u2022" }), _jsx("span", { className: "truncate max-w-[200px]", title: languages.join(", "), children: languages.join(", ") })] })) : null, totalJobs > 0 && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-gray-3", children: "\u2022" }), _jsxs("span", { className: "text-xs", children: [completedJobs, "/", totalJobs, " completed"] })] }))] }), _jsx("div", { className: "mt-2 block", children: _jsxs("span", { className: "inline-flex text-[10px] bg-gray-4 text-(--color-gray-1) px-2 py-0.5 rounded font-mono whitespace-nowrap overflow-hidden", children: ["ID: ", b.id] }) }), _jsxs("div", { className: "mt-2 flex flex-wrap gap-2 items-center text-xs", children: [info?.status && (_jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-1 font-medium ${info.status === 'Completed' ? 'bg-green-100 text-green-700' :
306
- info.status === 'In Progress' ? 'bg-theme-secondary-light text-theme-secondary' :
307
- info.status === 'Error' ? 'bg-red-100 text-red-600' : 'bg-gray-4 text-(--color-gray-1)'}`, children: info.status })), info?.provider && (_jsxs("span", { className: "text-(--color-gray-1)", children: ["Provider: ", _jsx("span", { className: "font-medium", children: info.provider })] })), info?.initiatedByUser && (_jsxs("span", { className: "text-(--color-gray-1)", children: ["By: ", _jsx("span", { className: "font-medium", children: info.initiatedByUser })] })), info?.lastUpdatedUtc && (_jsxs("span", { className: "text-gray-2", children: ["Updated: ", new Date(info.lastUpdatedUtc).toLocaleString()] }))] })] }), _jsxs("div", { className: "flex gap-2", children: [anyInProgress && (_jsx("span", { className: "rounded-full bg-theme-secondary-light px-3 py-1 text-xs font-medium text-theme-secondary", children: "In Progress" })), anyError && (_jsx("span", { className: "rounded-full bg-red-100 px-3 py-1 text-xs font-medium text-red-600", 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));
308
- }) })] }, dateGroup.label))), hasMore && (_jsx("div", { className: "flex justify-center pt-6", children: _jsx(Button, { variant: "outline", size: "sm", onClick: loadMore, disabled: isLoadingMore, children: isLoadingMore ? (_jsxs(_Fragment, { children: [_jsx(LoaderIcon, { className: "h-4 w-4 animate-spin text-theme-secondary" }), "Loading more..."] })) : (_jsxs(_Fragment, { children: [_jsx(ChevronDownIcon, { className: "h-4 w-4" }), "Load More Batches"] })) }) }))] })) })] }));
309
- }