diff --git a/frontend/src/components/FileTable.tsx b/frontend/src/components/FileTable.tsx index dbfbbc69e..9009d9b3c 100644 --- a/frontend/src/components/FileTable.tsx +++ b/frontend/src/components/FileTable.tsx @@ -79,6 +79,7 @@ const FileTable: ForwardRefRenderFunction = (props, re const columnHelper = createColumnHelper(); const [columnFilters, setColumnFilters] = useState([]); const [isLoading, setIsLoading] = useState(false); + const [isCancellingQueue, setIsCancellingQueue] = useState(false); const [statusFilter, setStatusFilter] = useState(''); const [filetypeFilter, setFiletypeFilter] = useState(''); const [fileSourceFilter, setFileSourceFilter] = useState(''); @@ -387,9 +388,13 @@ const FileTable: ForwardRefRenderFunction = (props, re return ( - + {info.row.original.fileSource} @@ -829,6 +834,64 @@ const FileTable: ForwardRefRenderFunction = (props, re } }, [connectionStatus, filesData.length, isReadOnlyUser]); + const refreshFileData = async () => { + try { + const res = await getSourceNodes(); + if (res.data && res.data.status !== 'Failed' && res.data.data.length) { + const updatedFiles = res.data.data + .map((item: SourceNode) => { + const existingFile = filesData.find((f) => f.name === item.fileName); + if (existingFile) { + // Check if file is in queue + const isInQueue = queue.items.some((f) => f.name === item.fileName); + return { + ...existingFile, + status: isInQueue ? 'Waiting' : getFileSourceStatus(item), + nodesCount: item?.nodeCount ?? existingFile.nodesCount, + relationshipsCount: item?.relationshipCount ?? existingFile.relationshipsCount, + processingTotalTime: item?.processingTime ?? existingFile.processingTotalTime, + }; + } + return existingFile; + }) + .filter(Boolean); + + setFilesData(updatedFiles as CustomFile[]); + } + } catch (error) { + console.error('Refresh failed:', error); + } + }; + + const cancelQueue = async () => { + if (queue.isEmpty()) { + showNormalToast('No files in queue to cancel'); + return; + } + + setIsCancellingQueue(true); + try { + const queuedFileNames = queue.items.map((f) => f.name as string).filter(Boolean); + const queuedFileSources = queue.items.map((f) => f.fileSource as string).filter(Boolean); + const res = await cancelAPI(queuedFileNames, queuedFileSources); + + if (res.data.status === 'Success') { + queue.clear(); + await refreshFileData(); + + showNormalToast(`Successfully cancelled ${queuedFileNames.length} waiting file(s)`); + } else { + throw new Error(res.data.error || 'Failed to cancel queue'); + } + } catch (err) { + if (err instanceof Error) { + showErrorToast(`Failed to cancel queue: ${err.message}`); + } + } finally { + setIsCancellingQueue(false); + } + }; + const cancelHandler = async (fileName: string, id: string, fileSource: string) => { setFilesData((prevfiles) => prevfiles.map((curfile) => { @@ -1032,14 +1095,44 @@ const FileTable: ForwardRefRenderFunction = (props, re ); } else if (connectionStatus) { + const queueSize = queue.size(); return ( - - - - - {`Large files may be partially processed up to 10K characters due to resource limit.`} - + + + + + + {`Large files may be partially processed up to 10K characters due to resource limit.`} + + {queueSize > 0 && ( + + + + {isCancellingQueue + ? 'Cancelling files in waiting queue...' + : `${queueSize} file${queueSize !== 1 ? 's' : ''} waiting in queue`} + + {!isReadOnlyUser && ( + + + + )} + + )} );