@@ -226,10 +226,14 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
226
226
const [ dbTables , setDbTables ] = useState < DBTable [ ] > ( [ ] ) ;
227
227
const [ selectedTabIndex , setSelectedTabIndex ] = useState ( 0 ) ;
228
228
229
- const [ errorMessage , setErrorMessage ] = useState < string | null > ( null ) ;
229
+ const [ errorMessage , setErrorMessage ] = useState < { content : string , severity : "error" | "warning" | "info" | "success" } | null > ( null ) ;
230
230
const [ showError , setShowError ] = useState ( false ) ;
231
231
const [ isUploading , setIsUploading ] = useState < boolean > ( false ) ;
232
232
233
+ useEffect ( ( ) => {
234
+ fetchTables ( ) ;
235
+ } , [ ] ) ;
236
+
233
237
// Fetch list of tables
234
238
const fetchTables = async ( ) => {
235
239
try {
@@ -267,7 +271,7 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
267
271
}
268
272
} catch ( error ) {
269
273
console . error ( 'Failed to upload table:' , error ) ;
270
- setErrorMessage ( 'Failed to upload table. The server may need to be restarted.' ) ;
274
+ setErrorMessage ( { content : 'Failed to upload table. The server may need to be restarted.' , severity : "error" } ) ;
271
275
setShowError ( true ) ;
272
276
} finally {
273
277
setIsUploading ( false ) ;
@@ -304,7 +308,7 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
304
308
URL . revokeObjectURL ( url ) ;
305
309
} catch ( error ) {
306
310
console . error ( 'Failed to download database:' , error ) ;
307
- setErrorMessage ( 'Failed to download database file' ) ;
311
+ setErrorMessage ( { content : 'Failed to download database file' , severity : "error" } ) ;
308
312
setShowError ( true ) ;
309
313
}
310
314
} ;
@@ -325,18 +329,25 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
325
329
} ) ;
326
330
const data = await response . json ( ) ;
327
331
if ( data . status === 'success' ) {
332
+ if ( data . is_renamed ) {
333
+ setErrorMessage ( { content : `Table ${ data . original_name } already exists. Renamed to ${ data . table_name } ` , severity : "warning" } ) ;
334
+ setShowError ( true ) ;
335
+ }
328
336
fetchTables ( ) ; // Refresh table list
329
337
} else {
330
- // Handle error from server
331
- setErrorMessage ( data . error || 'Failed to upload table' ) ;
338
+ setErrorMessage ( { content : data . error || 'Failed to upload table' , severity : "error" } ) ;
332
339
setShowError ( true ) ;
333
340
}
334
341
} catch ( error ) {
335
342
console . error ( 'Failed to upload table:' , error ) ;
336
- setErrorMessage ( 'Failed to upload table. The server may need to be restarted.' ) ;
343
+ setErrorMessage ( { content : 'Failed to upload table. The server may need to be restarted.' , severity : "error" } ) ;
337
344
setShowError ( true ) ;
338
345
} finally {
339
346
setIsUploading ( false ) ;
347
+ // Clear the file input value to allow uploading the same file again
348
+ if ( event . target ) {
349
+ event . target . value = '' ;
350
+ }
340
351
}
341
352
} ;
342
353
@@ -354,7 +365,7 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
354
365
}
355
366
} catch ( error ) {
356
367
console . error ( 'Failed to reset database:' , error ) ;
357
- setErrorMessage ( 'Failed to reset database' ) ;
368
+ setErrorMessage ( { content : 'Failed to reset database' , severity : "error" } ) ;
358
369
setShowError ( true ) ;
359
370
}
360
371
}
@@ -409,7 +420,7 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
409
420
}
410
421
} catch ( error ) {
411
422
console . error ( 'Failed to analyze table data:' , error ) ;
412
- setErrorMessage ( 'Failed to analyze table data' ) ;
423
+ setErrorMessage ( { content : 'Failed to analyze table data' , severity : "error" } ) ;
413
424
setShowError ( true ) ;
414
425
}
415
426
} ;
@@ -476,6 +487,44 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
476
487
}
477
488
} , [ tableDialogOpen ] ) ;
478
489
490
+ let importButton = ( buttonElement : React . ReactNode ) => {
491
+ return < Tooltip title = "import a duckdb .db file to the local database" >
492
+ < Button variant = "text" sx = { { fontSize : "inherit" , minWidth : "auto" } } component = "label" disabled = { isUploading } >
493
+ { buttonElement }
494
+ < input type = "file" hidden onChange = { handleDBUpload } accept = ".db" disabled = { isUploading } />
495
+ </ Button >
496
+ </ Tooltip >
497
+ }
498
+
499
+ let exportButton =
500
+ < Tooltip title = "save the local database to a duckdb .db file" >
501
+ < Button variant = "text" size = "small" onClick = { handleDBDownload } disabled = { isUploading || dbTables . length === 0 } >
502
+ export
503
+ </ Button >
504
+ </ Tooltip >
505
+
506
+ function uploadFileButton ( element : React . ReactNode , buttonSx ?: SxProps ) {
507
+ return (
508
+ < Tooltip title = "upload a csv/tsv file to the local database" >
509
+ < Button
510
+ variant = "text"
511
+ component = "label"
512
+ sx = { { fontSize : "inherit" , ...buttonSx } }
513
+ disabled = { isUploading }
514
+ >
515
+ { element }
516
+ < input
517
+ type = "file"
518
+ hidden
519
+ onChange = { handleFileUpload }
520
+ accept = ".csv,.xlsx,.json"
521
+ disabled = { isUploading }
522
+ />
523
+ </ Button >
524
+ </ Tooltip >
525
+ ) ;
526
+ }
527
+
479
528
let mainContent = dbTables . length > 0 ?
480
529
< Box sx = { { flexGrow : 1 , bgcolor : 'background.paper' , display : 'flex' , flexDirection : 'row' , height : '100%' } } >
481
530
< Box sx = { { display : "flex" , flexDirection : "column" , width : "120px" , borderRight : 1 , borderColor : 'divider' } } >
@@ -485,7 +534,7 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
485
534
value = { selectedTabIndex }
486
535
onChange = { handleTabChange }
487
536
aria-label = "Database tables"
488
- sx = { { width : '120px' } }
537
+ sx = { { width : '120px' , maxHeight : '360px' } }
489
538
>
490
539
{ dbTables . map ( ( t , i ) => (
491
540
< Tab
@@ -501,25 +550,7 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
501
550
) ) }
502
551
</ Tabs >
503
552
< Divider sx = { { my : 1 } } textAlign = 'left' > < TuneIcon sx = { { fontSize : 12 , color : "text.secondary" } } /> </ Divider >
504
- < Tooltip title = "upload a csv/tsv file to the local database" >
505
- < Button
506
- variant = "text"
507
- component = "label"
508
- size = "small"
509
- sx = { { width : '100%' , textTransform : "none" } }
510
- disabled = { isUploading }
511
- startIcon = { < UploadIcon fontSize = "small" /> }
512
- >
513
- { isUploading ? 'uploading...' : 'upload file' }
514
- < input
515
- type = "file"
516
- hidden
517
- onChange = { handleFileUpload }
518
- accept = ".csv,.xlsx,.json"
519
- disabled = { isUploading }
520
- />
521
- </ Button >
522
- </ Tooltip >
553
+ { uploadFileButton ( < Typography component = "span" fontSize = { 12 } > { isUploading ? 'uploading...' : 'upload file' } </ Typography > ) }
523
554
</ Box >
524
555
{ dbTables . map ( ( t , i ) => {
525
556
const currentTable = t ;
@@ -582,8 +613,12 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
582
613
</ Box > :
583
614
< Box sx = { { p : 3 , textAlign : 'center' , height : '100%' , display : 'flex' , flexDirection : 'column' , justifyContent : 'center' , alignItems : 'center' } } >
584
615
< StorageIcon sx = { { fontSize : 60 , color : 'text.secondary' , mb : 2 } } />
585
- < Typography variant = "h6" gutterBottom >
586
- Please upload a file to create a table
616
+ < Typography variant = "caption" > Database is currently empty. </ Typography >
617
+ < Typography >
618
+ { uploadFileButton ( < Typography component = "span" > Upload a csv dataset </ Typography > ) }
619
+ or
620
+ { importButton ( < Typography component = "span" > Import a db file</ Typography > ) }
621
+ < Typography component = "span" > to get started.</ Typography >
587
622
</ Typography >
588
623
</ Box >
589
624
@@ -602,8 +637,8 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
602
637
onClose = { handleCloseError }
603
638
anchorOrigin = { { vertical : 'top' , horizontal : 'center' } }
604
639
>
605
- < Alert onClose = { handleCloseError } severity = "error" sx = { { width : '100%' } } >
606
- { errorMessage }
640
+ < Alert onClose = { handleCloseError } severity = { errorMessage ?. severity } sx = { { width : '100%' } } >
641
+ { errorMessage ?. content }
607
642
</ Alert >
608
643
</ Snackbar >
609
644
@@ -649,30 +684,9 @@ export const DBTableSelectionDialog: React.FC<{ buttonElement: any }> = function
649
684
</ DialogContent >
650
685
< DialogActions >
651
686
< Typography variant = "caption" sx = { { mr : 'auto' , '& .MuiButton-root' : { minWidth : 'auto' , textTransform : "none" } } } >
652
- < Button
653
- variant = "text"
654
- size = "small"
655
- component = "label"
656
- disabled = { isUploading }
657
- >
658
- Reload
659
- < input
660
- type = "file"
661
- hidden
662
- onChange = { handleDBUpload }
663
- accept = ".db"
664
- disabled = { isUploading }
665
- />
666
- </ Button >
687
+ { importButton ( < Typography component = "span" fontSize = "inherit" > Import</ Typography > ) }
667
688
,
668
- < Button
669
- variant = "text" size = "small"
670
- // endIcon={<DownloadIcon />}
671
- onClick = { handleDBDownload }
672
- disabled = { isUploading || dbTables . length === 0 }
673
- >
674
- download
675
- </ Button >
689
+ { exportButton }
676
690
or
677
691
< Button
678
692
variant = "text" size = "small"
0 commit comments