Daniel.y commited on
Commit
a450594
·
unverified ·
2 Parent(s): 665092e 84e92c5

Merge pull request #1292 from danielaskdd/fix-promise-warning

Browse files

Fix promise warning and add null checks in FileUploader to prevent split() on undefined

lightrag/api/__init__.py CHANGED
@@ -1 +1 @@
1
- __api_version__ = "0138"
 
1
+ __api_version__ = "0139"
lightrag/api/webui/assets/{index-Bz5MOBb9.js → index-sivPufd7.js} RENAMED
Binary files a/lightrag/api/webui/assets/index-Bz5MOBb9.js and b/lightrag/api/webui/assets/index-sivPufd7.js differ
 
lightrag/api/webui/index.html CHANGED
Binary files a/lightrag/api/webui/index.html and b/lightrag/api/webui/index.html differ
 
lightrag_webui/src/App.tsx CHANGED
@@ -33,6 +33,26 @@ function App() {
33
  }
34
  }, [])
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  // Health check - can be disabled
37
  useEffect(() => {
38
  // Only execute if health check is enabled and ApiKeyAlert is closed
@@ -40,7 +60,14 @@ function App() {
40
 
41
  // Health check function
42
  const performHealthCheck = async () => {
43
- await useBackendState.getState().check();
 
 
 
 
 
 
 
44
  };
45
 
46
  // Set interval for periodic execution
 
33
  }
34
  }, [])
35
 
36
+ // Track component mount status with useRef
37
+ const isMountedRef = useRef(true);
38
+
39
+ // Set up mount/unmount status tracking
40
+ useEffect(() => {
41
+ isMountedRef.current = true;
42
+
43
+ // Handle page reload/unload
44
+ const handleBeforeUnload = () => {
45
+ isMountedRef.current = false;
46
+ };
47
+
48
+ window.addEventListener('beforeunload', handleBeforeUnload);
49
+
50
+ return () => {
51
+ isMountedRef.current = false;
52
+ window.removeEventListener('beforeunload', handleBeforeUnload);
53
+ };
54
+ }, []);
55
+
56
  // Health check - can be disabled
57
  useEffect(() => {
58
  // Only execute if health check is enabled and ApiKeyAlert is closed
 
60
 
61
  // Health check function
62
  const performHealthCheck = async () => {
63
+ try {
64
+ // Only perform health check if component is still mounted
65
+ if (isMountedRef.current) {
66
+ await useBackendState.getState().check();
67
+ }
68
+ } catch (error) {
69
+ console.error('Health check error:', error);
70
+ }
71
  };
72
 
73
  // Set interval for periodic execution
lightrag_webui/src/components/ui/FileUploader.tsx CHANGED
@@ -206,10 +206,15 @@ function FileUploader(props: FileUploaderProps) {
206
  if (onUpload && acceptedFiles.length > 0) {
207
  // Filter out any files that might have been rejected by our custom validator
208
  const validFiles = acceptedFiles.filter(file => {
 
 
 
 
 
209
  // Check if file type is accepted
210
  const fileExt = `.${file.name.split('.').pop()?.toLowerCase() || ''}`;
211
  const isAccepted = Object.entries(accept || {}).some(([mimeType, extensions]) => {
212
- return file.type === mimeType || extensions.includes(fileExt);
213
  });
214
 
215
  // Check file size
@@ -260,10 +265,22 @@ function FileUploader(props: FileUploaderProps) {
260
  multiple={maxFileCount > 1 || multiple}
261
  disabled={isDisabled}
262
  validator={(file) => {
263
- // Check if file type is accepted
 
 
 
 
 
 
 
 
 
264
  const fileExt = `.${file.name.split('.').pop()?.toLowerCase() || ''}`;
 
 
265
  const isAccepted = Object.entries(accept || {}).some(([mimeType, extensions]) => {
266
- return file.type === mimeType || extensions.includes(fileExt);
 
267
  });
268
 
269
  if (!isAccepted) {
 
206
  if (onUpload && acceptedFiles.length > 0) {
207
  // Filter out any files that might have been rejected by our custom validator
208
  const validFiles = acceptedFiles.filter(file => {
209
+ // Skip files without a name
210
+ if (!file.name) {
211
+ return false;
212
+ }
213
+
214
  // Check if file type is accepted
215
  const fileExt = `.${file.name.split('.').pop()?.toLowerCase() || ''}`;
216
  const isAccepted = Object.entries(accept || {}).some(([mimeType, extensions]) => {
217
+ return file.type === mimeType || (Array.isArray(extensions) && extensions.includes(fileExt));
218
  });
219
 
220
  // Check file size
 
265
  multiple={maxFileCount > 1 || multiple}
266
  disabled={isDisabled}
267
  validator={(file) => {
268
+ // Ensure file name exists
269
+ if (!file.name) {
270
+ return {
271
+ code: 'invalid-file-name',
272
+ message: t('documentPanel.uploadDocuments.fileUploader.invalidFileName',
273
+ { fallback: 'Invalid file name' })
274
+ };
275
+ }
276
+
277
+ // Safely extract file extension
278
  const fileExt = `.${file.name.split('.').pop()?.toLowerCase() || ''}`;
279
+
280
+ // Ensure accept object exists and has correct format
281
  const isAccepted = Object.entries(accept || {}).some(([mimeType, extensions]) => {
282
+ // Ensure extensions is an array before calling includes
283
+ return file.type === mimeType || (Array.isArray(extensions) && extensions.includes(fileExt));
284
  });
285
 
286
  if (!isAccepted) {
lightrag_webui/src/features/DocumentManager.tsx CHANGED
@@ -137,6 +137,26 @@ type SortField = 'created_at' | 'updated_at' | 'id';
137
  type SortDirection = 'asc' | 'desc';
138
 
139
  export default function DocumentManager() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  const [showPipelineStatus, setShowPipelineStatus] = useState(false)
141
  const { t } = useTranslation()
142
  const health = useBackendState.use.health()
@@ -324,7 +344,13 @@ export default function DocumentManager() {
324
 
325
  const fetchDocuments = useCallback(async () => {
326
  try {
327
- const docs = await getDocuments()
 
 
 
 
 
 
328
 
329
  // Get new status counts (treat null as all zeros)
330
  const newStatusCounts = {
@@ -339,30 +365,36 @@ export default function DocumentManager() {
339
  status => newStatusCounts[status] !== prevStatusCounts.current[status]
340
  )
341
 
342
- // Trigger health check if changes detected
343
- if (hasStatusCountChange) {
344
  useBackendState.getState().check()
345
  }
346
 
347
- // Update previous status counts
348
- prevStatusCounts.current = newStatusCounts
349
-
350
- // Update docs state
351
- if (docs && docs.statuses) {
352
- const numDocuments = Object.values(docs.statuses).reduce(
353
- (acc, status) => acc + status.length,
354
- 0
355
- )
356
- if (numDocuments > 0) {
357
- setDocs(docs)
 
 
 
 
 
358
  } else {
359
  setDocs(null)
360
  }
361
- } else {
362
- setDocs(null)
363
  }
364
  } catch (err) {
365
- toast.error(t('documentPanel.documentManager.errors.loadFailed', { error: errorMessage(err) }))
 
 
 
366
  }
367
  }, [setDocs, t])
368
 
@@ -375,10 +407,20 @@ export default function DocumentManager() {
375
 
376
  const scanDocuments = useCallback(async () => {
377
  try {
378
- const { status } = await scanNewDocuments()
379
- toast.message(status)
 
 
 
 
 
 
 
380
  } catch (err) {
381
- toast.error(t('documentPanel.documentManager.errors.scanFailed', { error: errorMessage(err) }))
 
 
 
382
  }
383
  }, [t])
384
 
@@ -390,13 +432,21 @@ export default function DocumentManager() {
390
 
391
  const interval = setInterval(async () => {
392
  try {
393
- await fetchDocuments()
 
 
 
394
  } catch (err) {
395
- toast.error(t('documentPanel.documentManager.errors.scanProgressFailed', { error: errorMessage(err) }))
 
 
 
396
  }
397
  }, 5000)
398
 
399
- return () => clearInterval(interval)
 
 
400
  }, [health, fetchDocuments, t, currentTab])
401
 
402
  // Add dependency on sort state to re-render when sort changes
 
137
  type SortDirection = 'asc' | 'desc';
138
 
139
  export default function DocumentManager() {
140
+ // Track component mount status
141
+ const isMountedRef = useRef(true);
142
+
143
+ // Set up mount/unmount status tracking
144
+ useEffect(() => {
145
+ isMountedRef.current = true;
146
+
147
+ // Handle page reload/unload
148
+ const handleBeforeUnload = () => {
149
+ isMountedRef.current = false;
150
+ };
151
+
152
+ window.addEventListener('beforeunload', handleBeforeUnload);
153
+
154
+ return () => {
155
+ isMountedRef.current = false;
156
+ window.removeEventListener('beforeunload', handleBeforeUnload);
157
+ };
158
+ }, []);
159
+
160
  const [showPipelineStatus, setShowPipelineStatus] = useState(false)
161
  const { t } = useTranslation()
162
  const health = useBackendState.use.health()
 
344
 
345
  const fetchDocuments = useCallback(async () => {
346
  try {
347
+ // Check if component is still mounted before starting the request
348
+ if (!isMountedRef.current) return;
349
+
350
+ const docs = await getDocuments();
351
+
352
+ // Check again if component is still mounted after the request completes
353
+ if (!isMountedRef.current) return;
354
 
355
  // Get new status counts (treat null as all zeros)
356
  const newStatusCounts = {
 
365
  status => newStatusCounts[status] !== prevStatusCounts.current[status]
366
  )
367
 
368
+ // Trigger health check if changes detected and component is still mounted
369
+ if (hasStatusCountChange && isMountedRef.current) {
370
  useBackendState.getState().check()
371
  }
372
 
373
+ // Only update state if component is still mounted
374
+ if (isMountedRef.current) {
375
+ // Update previous status counts
376
+ prevStatusCounts.current = newStatusCounts
377
+
378
+ // Update docs state
379
+ if (docs && docs.statuses) {
380
+ const numDocuments = Object.values(docs.statuses).reduce(
381
+ (acc, status) => acc + status.length,
382
+ 0
383
+ )
384
+ if (numDocuments > 0) {
385
+ setDocs(docs)
386
+ } else {
387
+ setDocs(null)
388
+ }
389
  } else {
390
  setDocs(null)
391
  }
 
 
392
  }
393
  } catch (err) {
394
+ // Only show error if component is still mounted
395
+ if (isMountedRef.current) {
396
+ toast.error(t('documentPanel.documentManager.errors.loadFailed', { error: errorMessage(err) }))
397
+ }
398
  }
399
  }, [setDocs, t])
400
 
 
407
 
408
  const scanDocuments = useCallback(async () => {
409
  try {
410
+ // Check if component is still mounted before starting the request
411
+ if (!isMountedRef.current) return;
412
+
413
+ const { status } = await scanNewDocuments();
414
+
415
+ // Check again if component is still mounted after the request completes
416
+ if (!isMountedRef.current) return;
417
+
418
+ toast.message(status);
419
  } catch (err) {
420
+ // Only show error if component is still mounted
421
+ if (isMountedRef.current) {
422
+ toast.error(t('documentPanel.documentManager.errors.scanFailed', { error: errorMessage(err) }));
423
+ }
424
  }
425
  }, [t])
426
 
 
432
 
433
  const interval = setInterval(async () => {
434
  try {
435
+ // Only perform fetch if component is still mounted
436
+ if (isMountedRef.current) {
437
+ await fetchDocuments()
438
+ }
439
  } catch (err) {
440
+ // Only show error if component is still mounted
441
+ if (isMountedRef.current) {
442
+ toast.error(t('documentPanel.documentManager.errors.scanProgressFailed', { error: errorMessage(err) }))
443
+ }
444
  }
445
  }, 5000)
446
 
447
+ return () => {
448
+ clearInterval(interval)
449
+ }
450
  }, [health, fetchDocuments, t, currentTab])
451
 
452
  // Add dependency on sort state to re-render when sort changes