Mail & Vendor: Async Bulk Document Updates, Searchable Upload-Center Filter, and Reliable Large Downloads (QA)
Executive summary
This release promotes a batch of frontend changes from development to the QA environment for testing. It adds progress tracking for large document bulk-update operations in the Mail app, makes the Vendor app's Upload Activity center filter searchable and faster to load, and fixes large-file downloads and PDF handling in the Vendor app.
Why this was needed
Several pain points were addressed at once: (1) updating the status or document type of 50+ documents at once now runs in the background on the server, but the Mail app still assumed it finished instantly — so users saw a misleading success message and stale data. (2) The Vendor app's Upload Activity filter eagerly loaded up to 100 upload centers on every page load, which was slow and unwieldy. (3) Large vendor downloads (e.g. 80MB+ ZIP files) were buffered fully in memory and frequently failed. (4) The Vendor app's PDF dependency tried to resolve an optional native package, breaking the dev build.
Client / user impact
- Mail users: Bulk updates over the size threshold now show a live progress panel (queued → processing → complete) that auto-refreshes the grid when done, instead of a false success toast over stale data.
- Vendor users: The upload-center filter opens instantly and loads results as you scroll/search rather than pre-loading everything; large file and ZIP downloads now stream directly to disk reliably; the "Download original" action only appears when an original file actually exists.
- This is a QA-stage promotion, so impact is for internal testing first, not yet production clients.
Technical scope
Batch promotion (dev → qa) bundling three feature efforts:
- #1052 — Async document bulk update: Extends the existing async background-job system (built for mail) with a
"document"operation type rather than new infrastructure. Adds a job-status route (/v1/documents/bulk-update-jobs/{id}), polling service/query (useDocumentJobPolling), document status config and operation-level failure panel, document cache-invalidation keys, and anonCompletehandler. Call sites inDocumentContents,DocumentGrid, andAssignDocumentTypeModalbranch on a 202 response. The WS+poll merge was extracted into a sharedbuildJobProgressDatahelper. The sync (<50) path is unchanged. - #1054 — Vendor Upload Activity: Replaces the eager 100-item
<Select>with a lazy, searchable, infinite-scroll combobox (UploadCenterAsyncSelect, IntersectionObserver-based paging, 20/page server-side search); switchesfetchAndDownloadFileinapps/vendor/src/lib/utils.tsto a direct-anchor download (no in-memory buffering); hides "Download original" when no original URL exists. - Vendor PDF/canvas fix (
4e0f0a4e): Externalizes the optionalcanvasdependency of pdfjs-dist via Next.jsserverExternalPackages, Turbopack alias to a stub (src/stubs/canvas.js), and webpackcanvas: falsefallback. - Shared types:
BackgroundJobStatusResponsewidened for the document endpoint;BackgroundJobFailedDetailnow models operation-level failures.
Risk & mitigation
Known blocking risk (called out in the PR): the backend async worker that #1052 drives is broken (a SQLAlchemy greenlet_spawn error). On the affected backend, bulk updates of ≥50 documents return 202 but the job never completes — the progress panel shows an indeterminate "Updating documents…" state forever, and re-submits return 500. The sync (<50) path is unaffected. Mitigation: do not rely on the async path in QA until the backend greenlet_spawn fix is confirmed deployed; no further frontend change is needed once it is. The vendor changes (download streaming, filter, canvas) are lower risk and verified on Dev.
QA validation focus
- Critical: Confirm the backend async worker fix is deployed to QA, then verify a ≥50-document status/type bulk update: 202 → panel advances queued → running → succeeded → grid auto-refreshes; also confirm the poll endpoint reaches a terminal status. Verify partial-failure (completed-with-errors) shows operation-level failure details.
- Verify <50-document bulk updates still complete synchronously with a success toast and grid refresh (no panel).
- Vendor: open Upload Activity filter — confirm it loads nothing until opened, searches server-side, infinite-scrolls, and resets to the full list after a selection; confirm the results footer/pagination is not clipped.
- Vendor: download a large (80MB+) parent ZIP and a single file — confirm reliable download with correct filename; confirm "Download original" is hidden for still-processing rows.
- Vendor: confirm PDF preview/handling works and the build runs (canvas externalization).