@parhelia/localization 0.1.12909 → 0.1.12910

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":"TranslationBatches.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationBatches.tsx"],"names":[],"mappings":"AAwPA,wBAAgB,kBAAkB,4CA6uCjC"}
1
+ {"version":3,"file":"TranslationBatches.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationBatches.tsx"],"names":[],"mappings":"AAwPA,wBAAgB,kBAAkB,4CAoxCjC"}
@@ -328,6 +328,38 @@ export function TranslationBatches() {
328
328
  useEffect(() => {
329
329
  const removeSocketMessageListener = editContext?.addSocketMessageListener((message) => {
330
330
  const batchIdFromPayload = normalizeGuid(message?.payload?.batchId ?? message?.payload?.BatchId);
331
+ // Live progress: patch the matching job's message in-place so an open
332
+ // popover reflects the latest progress text without a REST reload.
333
+ if (message.type === "translation-progress" && batchIdFromPayload) {
334
+ const itemIdFromPayload = normalizeGuid(message?.payload?.itemId ?? message?.payload?.ItemId);
335
+ const languageFromPayload = (message?.payload?.language ??
336
+ message?.payload?.Language ??
337
+ "").toString();
338
+ const progressMessage = (message?.payload?.message ??
339
+ message?.payload?.Message ??
340
+ "").toString();
341
+ if (itemIdFromPayload && languageFromPayload && progressMessage) {
342
+ setBatchJobs((prev) => {
343
+ const jobs = prev[batchIdFromPayload];
344
+ if (!jobs)
345
+ return prev;
346
+ let changed = false;
347
+ const nextJobs = jobs.map((job) => {
348
+ if (normalizeGuid(job.itemId) === itemIdFromPayload &&
349
+ job.targetLanguage === languageFromPayload &&
350
+ job.message !== progressMessage) {
351
+ changed = true;
352
+ return { ...job, message: progressMessage };
353
+ }
354
+ return job;
355
+ });
356
+ if (!changed)
357
+ return prev;
358
+ return { ...prev, [batchIdFromPayload]: nextJobs };
359
+ });
360
+ }
361
+ return;
362
+ }
331
363
  if (message.type === "batch-completed" ||
332
364
  ((message.type === "translation-started" ||
333
365
  message.type === "translation-finished" ||
@@ -1168,7 +1200,13 @@ function LanguageJobChip({ job, language, batchStartedAtUtc, onOpen, isRetrying
1168
1200
  : null;
1169
1201
  return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: `inline-flex items-center gap-1.5 rounded-md border badge-pad-sm text-[12px] transition-colors cursor-pointer ${chipCls}`, children: [language?.icon ? (_jsx("img", { src: language.icon, alt: langName, className: "h-3.5 shrink-0" })) : null, _jsx("span", { className: "font-mono tracking-tight", children: job.targetLanguage }), jobInProgress && (_jsx(LoaderIcon, { className: "h-3 w-3 shrink-0 animate-spin" })), jobPending && (_jsx(QueuedIcon, { className: "h-3 w-3 shrink-0", strokeWidth: 1.75, "aria-label": "Queued" })), jobError && _jsx(AlertCircleIcon, { className: "h-3 w-3 shrink-0" }), !jobInProgress && !jobError && !jobPending && !jobAborted && (_jsx(CheckIcon, { className: "h-3 w-3 shrink-0 text-feedback-green" }))] }) }), _jsxs(PopoverContent, { align: "start", sideOffset: 6, className: "w-[22rem] max-w-[calc(100vw-2rem)] p-0", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-border-default px-3 py-2", children: [language?.icon ? (_jsx("img", { src: language.icon, alt: langName, className: "h-4 shrink-0" })) : null, _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-[13px] font-medium text-neutral-grey-100 truncate", children: langName }), _jsxs("div", { className: "text-[11px] text-neutral-grey-50 font-mono truncate", children: [job.targetLanguage, job.sourceLanguage ? ` ← ${job.sourceLanguage}` : ""] })] }), _jsxs(Badge, { size: "sm", className: statusBadgeCls, children: [jobInProgress && (_jsx(LoaderIcon, { className: "h-2.5 w-2.5 animate-spin" })), jobStatus || "Unknown"] })] }), _jsxs("dl", { className: "divide-y divide-border-default/60", children: [claimedAtValid && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Claimed" }), _jsx("dd", { className: "text-[12px] text-neutral-grey-100", children: claimedAt.toLocaleString() })] })), timestampValid && (jobInProgress || jobPending) && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Updated" }), _jsx("dd", { className: "text-[12px] text-neutral-grey-100", children: timestamp.toLocaleString() })] })), durationMs != null && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: jobInProgress || jobPending ? "Running" : "Duration" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", title: durationApproximated
1170
1202
  ? "Approximate — measured from batch start"
1171
- : undefined, children: [durationApproximated ? "~" : "", formatDuration(durationMs)] })] })), statistics && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Fields" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: [fieldText, emptyFieldText ? (_jsxs("span", { className: "ml-1.5 text-neutral-grey-50", children: ["(", emptyFieldText, ")"] })) : null] })] })), statistics && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Text" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: [formatCount(statistics.sourceCharacterCount), " chars"] })] })), job.totalCost != null && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Cost" }), _jsx("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: formatUsdCost(job.totalCost) })] })), lastHeartbeatValid && (jobInProgress || jobPending) && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Heartbeat" }), _jsx("dd", { className: "text-[12px] text-neutral-grey-100", children: lastHeartbeat.toLocaleString() })] })), attemptCount > 1 && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Attempts" }), _jsx("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: attemptCount })] })), job.hash && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Hash" }), _jsx("dd", { className: "text-[11px] font-mono text-neutral-grey-100 break-all", children: job.hash })] })), job.message && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: jobError ? "Error" : jobAborted ? "Aborted" : "Message" }), _jsx("dd", { className: `text-[12px] break-words ${jobError ? "text-feedback-red" : jobAborted ? "text-feedback-orange" : "text-neutral-grey-100"}`, children: job.message })] })), job.batchId && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Batch" }), _jsx("dd", { className: "text-[11px] font-mono text-neutral-grey-50 break-all", children: job.batchId })] }))] }), _jsxs("div", { className: "flex justify-end gap-2 border-t border-border-default px-3 py-2", children: [jobError && onRetry && (_jsxs(Button, { size: "sm", variant: "outline", disabled: isRetrying, onClick: (e) => {
1203
+ : undefined, children: [durationApproximated ? "~" : "", formatDuration(durationMs)] })] })), statistics && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Fields" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: [fieldText, emptyFieldText ? (_jsxs("span", { className: "ml-1.5 text-neutral-grey-50", children: ["(", emptyFieldText, ")"] })) : null] })] })), statistics && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Text" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: [formatCount(statistics.sourceCharacterCount), " chars"] })] })), job.totalCost != null && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Cost" }), _jsx("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: formatUsdCost(job.totalCost) })] })), lastHeartbeatValid && (jobInProgress || jobPending) && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Heartbeat" }), _jsx("dd", { className: "text-[12px] text-neutral-grey-100", children: lastHeartbeat.toLocaleString() })] })), attemptCount > 1 && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Attempts" }), _jsx("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: attemptCount })] })), job.hash && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Hash" }), _jsx("dd", { className: "text-[11px] font-mono text-neutral-grey-100 break-all", children: job.hash })] })), job.message &&
1204
+ (jobError || jobAborted ? (
1205
+ // Error/abort messages can be long and multi-line (e.g. an external
1206
+ // ITranslationService stack trace). Render them in a bounded,
1207
+ // scrollable monospace block so the popover stays a sensible size and
1208
+ // the original formatting is preserved.
1209
+ _jsxs("div", { className: "flex flex-col gap-1 px-3 py-2", children: [_jsx("dt", { className: "text-[10px] tracking-wide text-neutral-grey-50", children: jobError ? "Error" : "Aborted" }), _jsx("dd", { className: `max-h-40 overflow-auto whitespace-pre-wrap break-words rounded-sm bg-neutral-grey-5 p-2 font-mono text-[11px] leading-snug ${jobError ? "text-feedback-red" : "text-feedback-orange"}`, children: job.message })] })) : (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Progress" }), _jsx("dd", { className: "text-[12px] break-words text-neutral-grey-100", children: job.message })] }))), job.batchId && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Batch" }), _jsx("dd", { className: "text-[11px] font-mono text-neutral-grey-50 break-all", children: job.batchId })] }))] }), _jsxs("div", { className: "flex justify-end gap-2 border-t border-border-default px-3 py-2", children: [jobError && onRetry && (_jsxs(Button, { size: "sm", variant: "outline", disabled: isRetrying, onClick: (e) => {
1172
1210
  e.stopPropagation();
1173
1211
  void onRetry();
1174
1212
  setOpen(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parhelia/localization",
3
- "version": "0.1.12909",
3
+ "version": "0.1.12910",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"