Merge pull request #1292 from danielaskdd/fix-promise-warning
Fix promise warning and add null checks in FileUploader to prevent split() on undefined
This commit is contained in:
@@ -1 +1 @@
|
|||||||
__api_version__ = "0138"
|
__api_version__ = "0139"
|
||||||
|
File diff suppressed because one or more lines are too long
2
lightrag/api/webui/index.html
generated
2
lightrag/api/webui/index.html
generated
@@ -8,7 +8,7 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="logo.png" />
|
<link rel="icon" type="image/svg+xml" href="logo.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Lightrag</title>
|
<title>Lightrag</title>
|
||||||
<script type="module" crossorigin src="/webui/assets/index-Bz5MOBb9.js"></script>
|
<script type="module" crossorigin src="/webui/assets/index-sivPufd7.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/webui/assets/index-CQhBIpFe.css">
|
<link rel="stylesheet" crossorigin href="/webui/assets/index-CQhBIpFe.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@@ -33,6 +33,26 @@ function App() {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
// Track component mount status with useRef
|
||||||
|
const isMountedRef = useRef(true);
|
||||||
|
|
||||||
|
// Set up mount/unmount status tracking
|
||||||
|
useEffect(() => {
|
||||||
|
isMountedRef.current = true;
|
||||||
|
|
||||||
|
// Handle page reload/unload
|
||||||
|
const handleBeforeUnload = () => {
|
||||||
|
isMountedRef.current = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
isMountedRef.current = false;
|
||||||
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Health check - can be disabled
|
// Health check - can be disabled
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Only execute if health check is enabled and ApiKeyAlert is closed
|
// Only execute if health check is enabled and ApiKeyAlert is closed
|
||||||
@@ -40,7 +60,14 @@ function App() {
|
|||||||
|
|
||||||
// Health check function
|
// Health check function
|
||||||
const performHealthCheck = async () => {
|
const performHealthCheck = async () => {
|
||||||
|
try {
|
||||||
|
// Only perform health check if component is still mounted
|
||||||
|
if (isMountedRef.current) {
|
||||||
await useBackendState.getState().check();
|
await useBackendState.getState().check();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Health check error:', error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set interval for periodic execution
|
// Set interval for periodic execution
|
||||||
|
@@ -206,10 +206,15 @@ function FileUploader(props: FileUploaderProps) {
|
|||||||
if (onUpload && acceptedFiles.length > 0) {
|
if (onUpload && acceptedFiles.length > 0) {
|
||||||
// Filter out any files that might have been rejected by our custom validator
|
// Filter out any files that might have been rejected by our custom validator
|
||||||
const validFiles = acceptedFiles.filter(file => {
|
const validFiles = acceptedFiles.filter(file => {
|
||||||
|
// Skip files without a name
|
||||||
|
if (!file.name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if file type is accepted
|
// Check if file type is accepted
|
||||||
const fileExt = `.${file.name.split('.').pop()?.toLowerCase() || ''}`;
|
const fileExt = `.${file.name.split('.').pop()?.toLowerCase() || ''}`;
|
||||||
const isAccepted = Object.entries(accept || {}).some(([mimeType, extensions]) => {
|
const isAccepted = Object.entries(accept || {}).some(([mimeType, extensions]) => {
|
||||||
return file.type === mimeType || extensions.includes(fileExt);
|
return file.type === mimeType || (Array.isArray(extensions) && extensions.includes(fileExt));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check file size
|
// Check file size
|
||||||
@@ -260,10 +265,22 @@ function FileUploader(props: FileUploaderProps) {
|
|||||||
multiple={maxFileCount > 1 || multiple}
|
multiple={maxFileCount > 1 || multiple}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
validator={(file) => {
|
validator={(file) => {
|
||||||
// Check if file type is accepted
|
// Ensure file name exists
|
||||||
|
if (!file.name) {
|
||||||
|
return {
|
||||||
|
code: 'invalid-file-name',
|
||||||
|
message: t('documentPanel.uploadDocuments.fileUploader.invalidFileName',
|
||||||
|
{ fallback: 'Invalid file name' })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safely extract file extension
|
||||||
const fileExt = `.${file.name.split('.').pop()?.toLowerCase() || ''}`;
|
const fileExt = `.${file.name.split('.').pop()?.toLowerCase() || ''}`;
|
||||||
|
|
||||||
|
// Ensure accept object exists and has correct format
|
||||||
const isAccepted = Object.entries(accept || {}).some(([mimeType, extensions]) => {
|
const isAccepted = Object.entries(accept || {}).some(([mimeType, extensions]) => {
|
||||||
return file.type === mimeType || extensions.includes(fileExt);
|
// Ensure extensions is an array before calling includes
|
||||||
|
return file.type === mimeType || (Array.isArray(extensions) && extensions.includes(fileExt));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isAccepted) {
|
if (!isAccepted) {
|
||||||
|
@@ -137,6 +137,26 @@ type SortField = 'created_at' | 'updated_at' | 'id';
|
|||||||
type SortDirection = 'asc' | 'desc';
|
type SortDirection = 'asc' | 'desc';
|
||||||
|
|
||||||
export default function DocumentManager() {
|
export default function DocumentManager() {
|
||||||
|
// Track component mount status
|
||||||
|
const isMountedRef = useRef(true);
|
||||||
|
|
||||||
|
// Set up mount/unmount status tracking
|
||||||
|
useEffect(() => {
|
||||||
|
isMountedRef.current = true;
|
||||||
|
|
||||||
|
// Handle page reload/unload
|
||||||
|
const handleBeforeUnload = () => {
|
||||||
|
isMountedRef.current = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
isMountedRef.current = false;
|
||||||
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const [showPipelineStatus, setShowPipelineStatus] = useState(false)
|
const [showPipelineStatus, setShowPipelineStatus] = useState(false)
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const health = useBackendState.use.health()
|
const health = useBackendState.use.health()
|
||||||
@@ -324,7 +344,13 @@ export default function DocumentManager() {
|
|||||||
|
|
||||||
const fetchDocuments = useCallback(async () => {
|
const fetchDocuments = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const docs = await getDocuments()
|
// Check if component is still mounted before starting the request
|
||||||
|
if (!isMountedRef.current) return;
|
||||||
|
|
||||||
|
const docs = await getDocuments();
|
||||||
|
|
||||||
|
// Check again if component is still mounted after the request completes
|
||||||
|
if (!isMountedRef.current) return;
|
||||||
|
|
||||||
// Get new status counts (treat null as all zeros)
|
// Get new status counts (treat null as all zeros)
|
||||||
const newStatusCounts = {
|
const newStatusCounts = {
|
||||||
@@ -339,11 +365,13 @@ export default function DocumentManager() {
|
|||||||
status => newStatusCounts[status] !== prevStatusCounts.current[status]
|
status => newStatusCounts[status] !== prevStatusCounts.current[status]
|
||||||
)
|
)
|
||||||
|
|
||||||
// Trigger health check if changes detected
|
// Trigger health check if changes detected and component is still mounted
|
||||||
if (hasStatusCountChange) {
|
if (hasStatusCountChange && isMountedRef.current) {
|
||||||
useBackendState.getState().check()
|
useBackendState.getState().check()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only update state if component is still mounted
|
||||||
|
if (isMountedRef.current) {
|
||||||
// Update previous status counts
|
// Update previous status counts
|
||||||
prevStatusCounts.current = newStatusCounts
|
prevStatusCounts.current = newStatusCounts
|
||||||
|
|
||||||
@@ -361,9 +389,13 @@ export default function DocumentManager() {
|
|||||||
} else {
|
} else {
|
||||||
setDocs(null)
|
setDocs(null)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
// Only show error if component is still mounted
|
||||||
|
if (isMountedRef.current) {
|
||||||
toast.error(t('documentPanel.documentManager.errors.loadFailed', { error: errorMessage(err) }))
|
toast.error(t('documentPanel.documentManager.errors.loadFailed', { error: errorMessage(err) }))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}, [setDocs, t])
|
}, [setDocs, t])
|
||||||
|
|
||||||
// Fetch documents when the tab becomes visible
|
// Fetch documents when the tab becomes visible
|
||||||
@@ -375,10 +407,20 @@ export default function DocumentManager() {
|
|||||||
|
|
||||||
const scanDocuments = useCallback(async () => {
|
const scanDocuments = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const { status } = await scanNewDocuments()
|
// Check if component is still mounted before starting the request
|
||||||
toast.message(status)
|
if (!isMountedRef.current) return;
|
||||||
|
|
||||||
|
const { status } = await scanNewDocuments();
|
||||||
|
|
||||||
|
// Check again if component is still mounted after the request completes
|
||||||
|
if (!isMountedRef.current) return;
|
||||||
|
|
||||||
|
toast.message(status);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toast.error(t('documentPanel.documentManager.errors.scanFailed', { error: errorMessage(err) }))
|
// Only show error if component is still mounted
|
||||||
|
if (isMountedRef.current) {
|
||||||
|
toast.error(t('documentPanel.documentManager.errors.scanFailed', { error: errorMessage(err) }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [t])
|
}, [t])
|
||||||
|
|
||||||
@@ -390,13 +432,21 @@ export default function DocumentManager() {
|
|||||||
|
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
|
// Only perform fetch if component is still mounted
|
||||||
|
if (isMountedRef.current) {
|
||||||
await fetchDocuments()
|
await fetchDocuments()
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
// Only show error if component is still mounted
|
||||||
|
if (isMountedRef.current) {
|
||||||
toast.error(t('documentPanel.documentManager.errors.scanProgressFailed', { error: errorMessage(err) }))
|
toast.error(t('documentPanel.documentManager.errors.scanProgressFailed', { error: errorMessage(err) }))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}, 5000)
|
}, 5000)
|
||||||
|
|
||||||
return () => clearInterval(interval)
|
return () => {
|
||||||
|
clearInterval(interval)
|
||||||
|
}
|
||||||
}, [health, fetchDocuments, t, currentTab])
|
}, [health, fetchDocuments, t, currentTab])
|
||||||
|
|
||||||
// Add dependency on sort state to re-render when sort changes
|
// Add dependency on sort state to re-render when sort changes
|
||||||
|
Reference in New Issue
Block a user