From ebcaa98122a7415b41d74bfa2643f352d718e3ff Mon Sep 17 00:00:00 2001 From: Devin Foley Date: Thu, 30 Jul 2026 12:58:39 -0700 Subject: [PATCH] feat(ui): durable progress and error state for import preview and apply MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previewing or importing a large package stringifies and uploads tens of megabytes and the server walks thousands of files — minutes of work whose only feedback was a button label flip, and failures only surfaced as an auto-dismissing toast. Both actions now show a persistent progress panel with size-aware copy while pending, failures render as a persistent error panel with retry guidance alongside the existing toast, and a disabled preview button explains itself inline (no package chosen, or package over the inline limit). Tested: ui typecheck, CompanyImport suite. --- ui/src/pages/CompanyImport.tsx | 52 ++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/ui/src/pages/CompanyImport.tsx b/ui/src/pages/CompanyImport.tsx index 2e5d3ddd7b9..352fa6d46b2 100644 --- a/ui/src/pages/CompanyImport.tsx +++ b/ui/src/pages/CompanyImport.tsx @@ -29,6 +29,7 @@ import { ChevronRight, Download, Github, + Loader2, Package, Upload, } from "lucide-react"; @@ -1442,7 +1443,38 @@ export function CompanyImport() { > {previewMutation.isPending ? "Previewing..." : "Preview import"} + {!hasSource && !previewMutation.isPending && ( + + Choose a package above to enable the preview. + + )} + {inlineImportBlocked && ( + + Package too large for browser import — see the notice above. + + )} + {previewMutation.isPending && ( +
+ +

+ Uploading and analyzing your package + {inlinePreflight ? ` (about ${formatMegabytes(inlinePreflight.estimatedBytes)})` : ""} — large + packages can take a few minutes. Keep this page open. +

+
+ )} + {previewMutation.isError && !previewMutation.isPending && ( +
+

+ Preview failed:{" "} + {previewMutation.error instanceof Error + ? previewMutation.error.message + : "the request did not complete."}{" "} + Retry, or use the CLI folder import for very large packages. +

+
+ )} {/* Preview results */} @@ -1514,6 +1546,26 @@ export function CompanyImport() { : `Import ${selectedCount} file${selectedCount === 1 ? "" : "s"}`} + {importMutation.isPending && ( +
+ +

+ Uploading and importing — large packages can take several minutes. Keep this page open. +

+
+ )} + {importMutation.isError && !importMutation.isPending && ( +
+

+ Import failed:{" "} + {importMutation.error instanceof Error + ? importMutation.error.message + : "the request did not complete."}{" "} + Nothing may have been created, or the import stopped partway — check the target company + before retrying. +

+
+ )} {/* Warnings */} {importPreview.warnings.length > 0 && (