@@ -29,7 +29,7 @@ import CancelIcon from '@mui/icons-material/Cancel';
29
29
30
30
import ReactDiffViewer from 'react-diff-viewer'
31
31
32
- import { dfActions , dfSelectors , fetchFieldSemanticType } from '../app/dfSlice' ;
32
+ import { DataFormulatorState , dfActions , dfSelectors , fetchFieldSemanticType } from '../app/dfSlice' ;
33
33
import { useDispatch , useSelector } from 'react-redux' ;
34
34
import { useState } from 'react' ;
35
35
import { AppDispatch } from '../app/store' ;
@@ -254,24 +254,40 @@ export interface TableUploadDialogProps {
254
254
disabled : boolean ;
255
255
}
256
256
257
+ const getUniqueTableName = ( baseName : string , existingNames : Set < string > ) : string => {
258
+ let uniqueName = baseName ;
259
+ let counter = 1 ;
260
+ while ( existingNames . has ( uniqueName ) ) {
261
+ uniqueName = `${ baseName } _${ counter } ` ;
262
+ counter ++ ;
263
+ }
264
+ return uniqueName ;
265
+ } ;
266
+
257
267
export const TableUploadDialog : React . FC < TableUploadDialogProps > = ( { buttonElement, disabled } ) => {
258
268
const dispatch = useDispatch < AppDispatch > ( ) ;
259
269
const inputRef = React . useRef < HTMLInputElement > ( null ) ;
270
+ const existingTables = useSelector ( ( state : DataFormulatorState ) => state . tables ) ;
271
+ const existingNames = new Set ( existingTables . map ( t => t . id ) ) ;
260
272
261
273
let handleFileUpload = ( event : React . ChangeEvent < HTMLInputElement > ) : void => {
262
274
const files = event . target . files ;
263
-
275
+
264
276
if ( files ) {
265
277
for ( let file of files ) {
266
278
file . text ( ) . then ( ( text ) => {
267
- let table = loadDataWrapper ( file . name , text , file . type ) ;
279
+ const uniqueName = getUniqueTableName ( file . name , existingNames ) ;
280
+ let table = loadDataWrapper ( uniqueName , text , file . type ) ;
268
281
if ( table ) {
269
282
dispatch ( dfActions . addTable ( table ) ) ;
270
283
dispatch ( fetchFieldSemanticType ( table ) ) ;
271
284
}
272
285
} ) ;
273
286
}
274
287
}
288
+ if ( inputRef . current ) {
289
+ inputRef . current . value = '' ;
290
+ }
275
291
} ;
276
292
277
293
return (
@@ -306,72 +322,6 @@ export interface TableCopyDialogProps {
306
322
disabled : boolean ;
307
323
}
308
324
309
- export const TableCopyDialog : React . FC < TableCopyDialogProps > = ( { buttonElement, disabled } ) => {
310
-
311
- const [ dialogOpen , setDialogOpen ] = useState < boolean > ( false ) ;
312
- const [ tableName , setTableName ] = useState < string > ( "" ) ;
313
- const [ tableContent , setTableContent ] = useState < string > ( "" ) ;
314
-
315
- const dispatch = useDispatch < AppDispatch > ( ) ;
316
-
317
- let handleSubmitContent = ( ) : void => {
318
-
319
- let table : undefined | DictTable = undefined ;
320
- try {
321
- let content = JSON . parse ( tableContent ) ;
322
- table = createTableFromFromObjectArray ( tableName || 'dataset' , content ) ;
323
- } catch ( error ) {
324
- table = createTableFromText ( tableName || 'dataset' , tableContent ) ;
325
- }
326
-
327
- if ( table ) {
328
- dispatch ( dfActions . addTable ( table ) ) ;
329
- dispatch ( fetchFieldSemanticType ( table ) ) ;
330
- }
331
- } ;
332
-
333
- let dialog = < Dialog key = "table-selection-dialog" onClose = { ( ) => { setDialogOpen ( false ) } } open = { dialogOpen }
334
- sx = { { '& .MuiDialog-paper' : { maxWidth : '80%' , maxHeight : 800 , minWidth : 800 } } }
335
- >
336
- < DialogTitle sx = { { display : "flex" } } > Paste & Upload Data
337
- < IconButton
338
- sx = { { marginLeft : "auto" } }
339
- edge = "start"
340
- size = "small"
341
- color = "inherit"
342
- onClick = { ( ) => { setDialogOpen ( false ) ; } }
343
- aria-label = "close"
344
- >
345
- < CloseIcon fontSize = "inherit" />
346
- </ IconButton >
347
- </ DialogTitle >
348
- < DialogContent sx = { { overflowX : "hidden" , padding : 2 , display : "flex" , flexDirection : "column" } } dividers >
349
- < TextField sx = { { marginBottom : 1 } } size = "small" value = { tableName } onChange = { ( event ) => { setTableName ( event . target . value ) ; } }
350
- autoComplete = 'off' id = "outlined-basic" label = "dataset name" variant = "outlined" />
351
- < TextField autoFocus size = "small" id = "upload content" value = { tableContent } maxRows = { 20 }
352
- onChange = { ( event ) => { setTableContent ( event . target . value ) ; } }
353
- autoComplete = 'off'
354
- label = "content (csv, tsv, or json format)" variant = "outlined" multiline minRows = { 15 } />
355
- </ DialogContent >
356
- < DialogActions >
357
- < Button variant = "contained" size = "small" onClick = { ( ) => { setDialogOpen ( false ) ; } } > cancel</ Button >
358
- < Button variant = "contained" size = "small" onClick = { ( ) => { setDialogOpen ( false ) ; handleSubmitContent ( ) ; } } >
359
- upload
360
- </ Button >
361
- </ DialogActions >
362
- </ Dialog > ;
363
-
364
- return < >
365
- < Button sx = { { fontSize : "inherit" } } variant = "text" color = "primary"
366
- disabled = { disabled } onClick = { ( ) => { setDialogOpen ( true ) } } >
367
- { buttonElement }
368
- </ Button >
369
- { dialog }
370
- </ > ;
371
- }
372
-
373
-
374
-
375
325
export interface TableURLDialogProps {
376
326
buttonElement : any ;
377
327
disabled : boolean ;
@@ -473,14 +423,30 @@ export const TableCopyDialogV2: React.FC<TableCopyDialogProps> = ({ buttonElemen
473
423
let theme = useTheme ( )
474
424
475
425
const dispatch = useDispatch < AppDispatch > ( ) ;
426
+ const existingTables = useSelector ( ( state : DataFormulatorState ) => state . tables ) ;
427
+ const existingNames = new Set ( existingTables . map ( t => t . id ) ) ;
476
428
477
429
let handleSubmitContent = ( tableStr : string ) : void => {
478
- let table : undefined | DictTable = undefined ;
430
+ let table : undefined | DictTable = undefined ;
431
+
432
+ // Generate a short unique name based on content and time if no name provided
433
+ const defaultName = ( ( ) => {
434
+ const hashStr = tableStr . substring ( 0 , 100 ) + Date . now ( ) ;
435
+ const hashCode = hashStr . split ( '' ) . reduce ( ( acc , char ) => {
436
+ return ( ( acc << 5 ) - acc ) + char . charCodeAt ( 0 ) | 0 ;
437
+ } , 0 ) ;
438
+ const shortHash = Math . abs ( hashCode ) . toString ( 36 ) . substring ( 0 , 4 ) ;
439
+ return `data-${ shortHash } ` ;
440
+ } ) ( ) ;
441
+
442
+ const baseName = tableName || defaultName ;
443
+ const uniqueName = getUniqueTableName ( baseName , existingNames ) ;
444
+
479
445
try {
480
446
let content = JSON . parse ( tableStr ) ;
481
- table = createTableFromFromObjectArray ( tableName || 'data-0' , content ) ;
447
+ table = createTableFromFromObjectArray ( uniqueName , content ) ;
482
448
} catch ( error ) {
483
- table = createTableFromText ( tableName || 'data-0' , tableStr ) ;
449
+ table = createTableFromText ( uniqueName , tableStr ) ;
484
450
}
485
451
if ( table ) {
486
452
dispatch ( dfActions . addTable ( table ) ) ;
0 commit comments