From be7c2817b7721cea79d3e67ede354f4ee8ff23af Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sat, 30 May 2026 03:29:25 +0530 Subject: [PATCH] txn_dict --- src/FetchRequestDetail.tsx | 33 +++++++++++-------- .../fetch-requests/fetch-requests.models.ts | 5 ++- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/FetchRequestDetail.tsx b/src/FetchRequestDetail.tsx index 70c771d..8f370b1 100644 --- a/src/FetchRequestDetail.tsx +++ b/src/FetchRequestDetail.tsx @@ -81,19 +81,16 @@ function computeProgressPercent( return status === "processing" || status === "paused" ? 10 : 0; } -const stepLabels = ["Load Content", "Extract", "Validate", "Enrich", "Save"]; +const stepLabels = ["Load Content", "Extract", "Raw Expense", "Enrich", "Save"]; -function statusToActiveStep(status: FetchRequestStatus): number { - switch (status) { - case "pending": return -1; - case "processing": return 0; - case "paused": return 2; - case "raw_expenses_done": return 2; - case "enriched_done": return 3; - case "completed": return stepLabels.length; - case "failed": return 0; - default: return -1; - } +function computeActiveStep(status: FetchRequestStatus, seenSteps: Set): number { + if (status === "completed") return stepLabels.length; + if (seenSteps.has("complete")) return 4; + if (seenSteps.has("enrich") || status === "enriched_done") return 3; + if (seenSteps.has("txn_dicts") || status === "raw_expenses_done") return 2; + if (seenSteps.has("txn_blocks")) return 1; + if (seenSteps.has("load_content") || status === "processing" || status === "paused") return 0; + return -1; } function formatProgressMessage(msg: ProgressMessage): string { @@ -226,8 +223,15 @@ export default function FetchRequestDetail() { break; } } + + const terminalStatuses = new Set(["completed", "skipped", "paused"]); return sseEvents.filter((e, i) => { if (e.step === "txn_dicts" && e.status === "progress") return i === lastProgressIdx; + if (e.status === "started") { + return !sseEvents.slice(i + 1).some( + (later) => later.step === e.step && terminalStatuses.has(later.status), + ); + } return true; }); }, [sseEvents]); @@ -255,7 +259,8 @@ export default function FetchRequestDetail() { const displayParsedCount = React.useMemo(() => { if (liveParsedCount > 0) return liveParsedCount; const source = (fetchRequest as any)?.source; - if (source?.txn_dicts_count) return source.txn_dicts_count; + const persistedCount = source?.txn_dict_count ?? source?.txn_dicts_count ?? 0; + if (persistedCount > 0) return persistedCount; const dicts = source?.txn_dicts; if (Array.isArray(dicts) && dicts.length > 0) return dicts.length; return 0; @@ -298,7 +303,7 @@ export default function FetchRequestDetail() { } const req = fetchRequest as any; - const activeStep = statusToActiveStep(req.status); + const activeStep = computeActiveStep(req.status as FetchRequestStatus, seenSteps); const retryCount = req.retry_count ?? 0; const isRetryExhausted = retryCount >= RETRY_MAX; const pendingAmbiguities = ambiguities?.filter((a: any) => a.status === "pending") ?? []; diff --git a/src/features/fetch-requests/fetch-requests.models.ts b/src/features/fetch-requests/fetch-requests.models.ts index bac7c28..110f13a 100644 --- a/src/features/fetch-requests/fetch-requests.models.ts +++ b/src/features/fetch-requests/fetch-requests.models.ts @@ -13,6 +13,7 @@ export interface FileSource { raw_lines?: string[]; txn_blocks?: Record; txn_dicts?: Record[]; + txn_dict_count?: number; txn_dicts_count?: number; } @@ -21,6 +22,7 @@ export interface EmailSource { from_email?: string; subject?: string; raw_terms?: string[]; + txn_dict_count?: number; txn_dicts_count?: number; } @@ -84,7 +86,8 @@ export interface ResolveAmbiguityPayload { export type SSEEventStep = | "load_content" | "raw_lines" | "txn_blocks" | "txn_dicts" - | "resume_extract" | "extract" | "paused" | "complete" | "enrich"; + | "resume_extract" | "extract" | "paused" | "complete" | "enrich" + | "save_expenses"; export type SSEEventStatus = | "started" | "completed" | "skipped" | "paused" | "progress";