Fetch Request UI #9
Reference in New Issue
Block a user
No description provided.
Delete Branch "fetch-request-steps-ui"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Add Fetch Request pipeline UI with real-time SSE progress tracking, ambiguity resolution, enhanced list page with filtering/retry, and detail page with stepper/event feed. Includes new API primitives (
api.patch,usePatchhook) and extensive type definitions for SSE events, ambiguity resolution, and pipeline statuses.Changes by file
react-openapi/api/client.tsapi.patch()method (delegates toAxiosInstance.patch)react-openapi/hooks/useResource.tsusePatch()mutation hook — sends PATCH/{endpoint}/{id}with partial data, invalidates list + detail query caches on successsrc/FetchRequestDetail.tsx(new, +675 lines)Full detail page for a single fetch request, composed of:
LinearProgresswith percentage computed viacomputeProgressPercent():raw_lines/txn_blockseventdisplayParsedCount/txnBlockCount× 20%stepStats.enrich_count/txnDictCount× 50%stepStats.save_count/txnDictCount× 20%retryCount/RETRY_MAX) + "Retry" button if failed & not exhaustederror_messagedisplay, max-retries infoExtract→Raw Expense→Enrich→Save) with custom icons per state: completed (CheckCircle, green), active (CircularProgress, animating), paused (WarningAmber, amber), failed (ErrorIcon, red), inactive (step number, grey). Step count labels shown below each label (e.g.150/246,100/246)progressevent per step (txn_dicts,enrich,save_expenses)startedevents hidden when a terminal event (completed/skipped/paused/failed) followsload_contentevents excluded entirelypaused, shows ambiguity cards:EventSourceto{baseUrl}/fetch-requests/{id}/events:progress,completed,paused,failedeventspaused: refetch request + ambiguitiesfailed: refetch request + show error snackbar frommessage.errorcompleted/resume_extract: refetch requestsrc/FetchRequests.tsx(+347/−73 lines)Major enhancement to the list page:
useResourceByName("accounts"), provides dropdownresourceOverridesconfig (fetchRes.fields.source.schema.format.options), fallback["axis", "icici_ocr"]datetime-localtodate, capped at today's date/fetch-requests/{id}viauseNavigatecreated_atdescending[Fingerprint, Source, Account, Status, Created, Actions]to[ID, Account, Source, Date Range, Status, Retries, Created, Actions]retry_count/RETRY_MAXwhen >0, otherwise—error_messageon hover when presentstatusIconsmap: ScheduleIcon (pending), CircularProgress (processing), WarningAmber (paused), HourglassEmpty (raw_expenses_done/enriched_done), CheckCircle (completed), ErrorIcon (failed)formatApiError()handleRetry— PATCH{status: "pending"}on failed requests, success/error snackbarsrc/features/fetch-requests/fetch-requests.models.ts(+97 lines)New types and helpers:
"paused"toFetchRequestStatusFileSource: addedraw_lines,txn_blocks,txn_dicts,txn_dict_count,txn_dicts_countEmailSource: addedtxn_dict_count,txn_dicts_countFetchRequestaddedretry_countFetchRequestUpdate,AmbiguityCandidate,PendingAmbiguity,ResolveAmbiguityPayload,FetchRequestFiltersSSEEventStep:load_content | raw_lines | txn_blocks | txn_dicts | resume_extract | extract | paused | complete | enrich | save_expenses | pipelineSSEEventStatus:started | completed | skipped | paused | progress | failedProgressMessage:lines? | blocks? | count? | unit? | raw_ocr_line? | error?SSEEvent: { step, status, message }formatApiError()— parses FastAPI 422 validation detail arrays ("Missing: field_name"),RETRY_MAX = 3src/features/fetch-requests/index.ts(+13 lines)Barrel exports for all new types (
FetchRequestUpdate,FetchRequestFilters,PendingAmbiguity,AmbiguityCandidate,ResolveAmbiguityPayload,SSEEvent,SSEEventStep,SSEEventStatus,ProgressMessage), value exports (RETRY_MAX,formatApiError), and new hooks (useUpdateFetchRequest,useFetchRequestAmbiguities,useResolveAmbiguity)src/features/fetch-requests/useFetchRequests.ts(+49 lines)Added hooks:
useUpdateFetchRequest()→usePatch("fetch-requests")useFetchRequestAmbiguities(fetchRequestId)→useQueryforGET /fetch-requests/{id}/ambiguitiesuseResolveAmbiguity()→useMutationforPOST /ambiguities/{id}/resolvewith cache invalidation of both ambiguities and detail queriessrc/main.jsx(+2 lines)FetchRequestDetail{ path: "/fetch-requests/:id", component: FetchRequestDetail, headerTitle: "Fetch Request" }WIP: fetch-request-steps-uito Fetch Request UI