diff --git a/surfsense_backend/app/routes/editor_routes.py b/surfsense_backend/app/routes/editor_routes.py index 829b2cf69..0f986e416 100644 --- a/surfsense_backend/app/routes/editor_routes.py +++ b/surfsense_backend/app/routes/editor_routes.py @@ -139,9 +139,19 @@ async def get_editor_content( status_code=409, detail="This document is still being processed. Please wait a moment and try again.", ) + if state == "failed": + reason = ( + doc_status.get("reason", "Unknown error") + if isinstance(doc_status, dict) + else "Unknown error" + ) + raise HTTPException( + status_code=422, + detail=f"Processing failed: {reason}. You can delete this document and re-upload it.", + ) raise HTTPException( status_code=400, - detail="This document has no viewable content yet. It may still be syncing. Try again in a few seconds, or re-upload if the issue persists.", + detail="This document has no content. It may not have been processed correctly. Try deleting and re-uploading it.", ) markdown_content = "\n\n".join(chunk_contents) diff --git a/surfsense_web/components/documents/DocumentNode.tsx b/surfsense_web/components/documents/DocumentNode.tsx index 04cec5f89..478037520 100644 --- a/surfsense_web/components/documents/DocumentNode.tsx +++ b/surfsense_web/components/documents/DocumentNode.tsx @@ -82,11 +82,12 @@ export const DocumentNode = React.memo(function DocumentNode({ onContextMenuOpenChange, }: DocumentNodeProps) { const statusState = doc.status?.state ?? "ready"; - const isSelectable = statusState !== "pending" && statusState !== "processing"; + const isFailed = statusState === "failed"; + const isProcessing = statusState === "pending" || statusState === "processing"; + const isUnavailable = isProcessing || isFailed; + const isSelectable = !isUnavailable; const isEditable = - EDITABLE_DOCUMENT_TYPES.has(doc.document_type) && - statusState !== "pending" && - statusState !== "processing"; + EDITABLE_DOCUMENT_TYPES.has(doc.document_type) && !isUnavailable; const handleCheckChange = useCallback(() => { if (isSelectable) { @@ -103,7 +104,6 @@ export const DocumentNode = React.memo(function DocumentNode({ [doc.id] ); - const isProcessing = statusState === "pending" || statusState === "processing"; const [dropdownOpen, setDropdownOpen] = useState(false); const [exporting, setExporting] = useState(null); const [titleTooltipOpen, setTitleTooltipOpen] = useState(false); @@ -261,38 +261,38 @@ export const DocumentNode = React.memo(function DocumentNode({ className="w-40" onClick={(e) => e.stopPropagation()} > - onPreview(doc)} disabled={isProcessing}> - - Open + onPreview(doc)} disabled={isUnavailable}> + + Open + + {isEditable && ( + onEdit(doc)}> + + Edit - {isEditable && ( - onEdit(doc)}> - - Edit - - )} - onMove(doc)}> - - Move to... + )} + onMove(doc)}> + + Move to... + + {onExport && ( + + + + Export + + + + + + )} + {onVersionHistory && isVersionableType(doc.document_type) && ( + onVersionHistory(doc)}> + + Versions - {onExport && ( - - - - Export - - - - - - )} - {onVersionHistory && isVersionableType(doc.document_type) && ( - onVersionHistory(doc)}> - - Versions - - )} - onDelete(doc)}> + )} + onDelete(doc)}> Delete @@ -304,38 +304,38 @@ export const DocumentNode = React.memo(function DocumentNode({ {contextMenuOpen && ( e.stopPropagation()}> - onPreview(doc)} disabled={isProcessing}> - - Open + onPreview(doc)} disabled={isUnavailable}> + + Open + + {isEditable && ( + onEdit(doc)}> + + Edit - {isEditable && ( - onEdit(doc)}> - - Edit - - )} - onMove(doc)}> - - Move to... + )} + onMove(doc)}> + + Move to... + + {onExport && ( + + + + Export + + + + + + )} + {onVersionHistory && isVersionableType(doc.document_type) && ( + onVersionHistory(doc)}> + + Versions - {onExport && ( - - - - Export - - - - - - )} - {onVersionHistory && isVersionableType(doc.document_type) && ( - onVersionHistory(doc)}> - - Versions - - )} - onDelete(doc)}> + )} + onDelete(doc)}> Delete diff --git a/surfsense_web/components/layout/ui/sidebar/DocumentsSidebar.tsx b/surfsense_web/components/layout/ui/sidebar/DocumentsSidebar.tsx index 95bd21e3b..d69f48606 100644 --- a/surfsense_web/components/layout/ui/sidebar/DocumentsSidebar.tsx +++ b/surfsense_web/components/layout/ui/sidebar/DocumentsSidebar.tsx @@ -627,9 +627,10 @@ export function DocumentsSidebar({ function collectSubtreeDocs(parentId: number): DocumentNodeDoc[] { const directDocs = (treeDocuments ?? []).filter( (d) => - d.folderId === parentId && - d.status?.state !== "pending" && - d.status?.state !== "processing" + d.folderId === parentId && + d.status?.state !== "pending" && + d.status?.state !== "processing" && + d.status?.state !== "failed" ); const childFolders = foldersByParent[String(parentId)] ?? []; const descendantDocs = childFolders.flatMap((cf) => collectSubtreeDocs(cf.id));