Files
descrybe/apps/web/src/lib/job-status.ts
T
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

127 lines
4.2 KiB
TypeScript

import { i18n } from "$lib/i18n";
/** Message key for a processing job status (machine code → i18n). */
export function jobStatusMessageKey(status: string | null | undefined): string {
const s = (status ?? "").toLowerCase().trim();
if (s === "running" || s === "processing") return "status.processing";
if (s === "completed" || s === "success" || s === "done") return "status.completed";
if (s === "failed" || s === "error") return "status.failed";
if (s === "cancelled" || s === "canceled") return "status.cancelled";
if (s === "pending" || s === "queued") return "processing.jobStatus.queued";
if (s === "skipped") return "processing.jobStatus.skipped";
return "processing.jobStatus.unknown";
}
/** Localized label for a processing job status code (Queued for pending). */
export function formatJobStatusLabel(status: string | null | undefined): string {
const key = jobStatusMessageKey(status);
const label = i18n.t(key);
if (label !== key) return label;
const raw = (status ?? "").trim();
return raw || i18n.t("processing.jobStatus.unknown");
}
/** True while a processing job should appear in the global progress indicator. */
export function isActiveProcessingJob(status: string | null | undefined): boolean {
const s = (status ?? "").toLowerCase().trim();
return s === "pending" || s === "queued" || s === "running" || s === "processing";
}
/** Dashboard prefers shared "Pending" wording for queued jobs. */
export function formatJobStatusLabelPending(status: string | null | undefined): string {
const s = (status ?? "").toLowerCase().trim();
if (s === "pending" || s === "queued") {
return i18n.t("status.pending");
}
const label = formatJobStatusLabel(status);
if (!status?.trim()) return i18n.t("status.emDash");
return label;
}
const JOB_ERR_KEYS = new Set([
"processing.job.error.all_failed",
"processing.job.error.partial_failed"
]);
/**
* Localize pipeline job.error values.
* Accepts keyed payloads from FormatJobUserError (`key|count=N`) and legacy English prose.
*/
export function formatJobErrorText(raw: string | null | undefined): string {
const text = (raw ?? "").trim();
if (!text) return "";
const cut = text.indexOf("|count=");
if (cut > 0) {
const key = text.slice(0, cut).trim();
const countRaw = text.slice(cut + "|count=".length).trim();
const count = Number(countRaw);
if (JOB_ERR_KEYS.has(key) && Number.isFinite(count)) {
return i18n.t(key, { count });
}
}
return text;
}
/** Localized pipeline step name. */
export function formatJobStepLabel(step: string | null | undefined): string {
const s = (step ?? "").trim();
switch (s) {
case "normalize":
return i18n.t("processing.step.normalize");
case "parse_specs":
return i18n.t("processing.step.parse_specs");
case "fill_fields":
return i18n.t("processing.step.fill_fields");
case "eprel":
return i18n.t("processing.step.eprel");
case "ai_enhance":
return i18n.t("processing.step.ai_enhance");
default:
return s || i18n.t("processing.jobStatus.unknown");
}
}
/** Message key for a processing_type / job.type code. */
export function processingTypeMessageKey(type: string | null | undefined): string | null {
const s = (type ?? "").toLowerCase().trim().replaceAll("-", "_");
if (!s) return null;
switch (s) {
case "full":
return "processing.type.full";
case "enhance":
case "enhance_only":
return "processing.type.enhance_only";
case "title":
return "processing.type.title";
case "description":
return "processing.type.description";
case "attributes":
return "processing.type.attributes";
case "category":
return "processing.type.category";
case "eprel":
case "eprel_only":
return "processing.type.eprel";
case "seo":
case "seo_ai":
return "processing.type.seo";
case "normalize":
case "normalize_only":
return "processing.type.normalize";
default:
return null;
}
}
/** Localized processing job type (never show snake_case API codes when keyed). */
export function formatProcessingTypeLabel(type: string | null | undefined): string {
const key = processingTypeMessageKey(type);
if (key) {
const label = i18n.t(key);
if (label !== key) return label;
}
const raw = (type ?? "").trim();
if (!raw) return i18n.t("processing.jobStatus.unknown");
return raw.replaceAll("_", " ");
}