Skip to content

Commit 67362c5

Browse files
committed
fix various styling issues and button issues
1 parent b2f15a1 commit 67362c5

File tree

4 files changed

+92
-77
lines changed

4 files changed

+92
-77
lines changed

src/app/App.tsx

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import {
3333
DialogActions,
3434
ToggleButtonGroup,
3535
ToggleButton,
36+
Menu,
37+
MenuItem,
3638
} from '@mui/material';
3739

3840

@@ -59,6 +61,8 @@ import dfLogo from '../assets/df-logo.png';
5961
import { Popup } from '../components/Popup';
6062
import { ModelSelectionButton } from '../views/ModelSelectionDialog';
6163
import { TableCopyDialogV2 } from '../views/TableSelectionView';
64+
import { TableUploadDialog } from '../views/TableSelectionView';
65+
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
6266

6367
const AppBar = styled(MuiAppBar)(({ theme }) => ({
6468
color: 'black',
@@ -263,6 +267,15 @@ export const AppFC: FC<AppFCProps> = function AppFC(appProps) {
263267
</Box>
264268
)
265269

270+
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
271+
const open = Boolean(anchorEl);
272+
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
273+
setAnchorEl(event.currentTarget);
274+
};
275+
const handleClose = () => {
276+
setAnchorEl(null);
277+
};
278+
266279
let appBar = [
267280
<AppBar className="app-bar" position="static" key="app-bar-main">
268281
<Toolbar variant="dense" sx={{ backgroundColor: betaMode ? 'lavender' : '' }}>
@@ -289,7 +302,40 @@ export const AppFC: FC<AppFCProps> = function AppFC(appProps) {
289302
<Divider orientation="vertical" variant="middle" flexItem /> */}
290303
<ModelSelectionButton />
291304
<Divider orientation="vertical" variant="middle" flexItem />
292-
<TableCopyDialogV2 buttonElement={"ADD TABLE"} disabled={false} />
305+
<Typography sx={{ display: 'flex', fontSize: 14, alignItems: 'center', gap: 1 }}>
306+
<Button
307+
variant="text"
308+
onClick={handleClick}
309+
endIcon={<KeyboardArrowDownIcon />}
310+
aria-controls={open ? 'add-table-menu' : undefined}
311+
aria-haspopup="true"
312+
aria-expanded={open ? 'true' : undefined}
313+
>
314+
Add A Table
315+
</Button>
316+
<Menu
317+
id="add-table-menu"
318+
anchorEl={anchorEl}
319+
open={open}
320+
onClose={handleClose}
321+
MenuListProps={{
322+
'aria-labelledby': 'add-table-button',
323+
sx: { py: '2px' }
324+
}}
325+
sx={{ '& .MuiMenuItem-root': { padding: 0, margin: 0 } }}
326+
>
327+
<MenuItem onClick={(e) => {
328+
e.preventDefault();
329+
e.stopPropagation();
330+
}} sx={{ fontSize: 14, '& .MuiButton-root': { textTransform: 'none' } }}>
331+
<TableCopyDialogV2 buttonElement={"from clipboard"} disabled={false} />
332+
</MenuItem>
333+
<MenuItem onClick={(e) => {
334+
}} sx={{ fontSize: 14, '& .MuiButton-root': { textTransform: 'none' } }}>
335+
<TableUploadDialog buttonElement={"from file"} disabled={false} />
336+
</MenuItem>
337+
</Menu>
338+
</Typography>
293339
<Divider orientation="vertical" variant="middle" flexItem />
294340
<ExportStateButton />
295341
<ImportStateButton />

src/views/DataFormulator.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ import { DndProvider } from 'react-dnd'
3333
import { HTML5Backend } from 'react-dnd-html5-backend'
3434

3535
import { SelectableGroup } from 'react-selectable-fast';
36-
import { TableCopyDialogV2, TableSelectionDialog, TableURLDialog } from './TableSelectionView';
37-
import { TableCopyDialog, TableUploadDialog } from './TableSelectionView';
36+
import { TableCopyDialogV2, TableSelectionDialog } from './TableSelectionView';
37+
import { TableUploadDialog } from './TableSelectionView';
3838
import { toolName } from '../app/App';
3939
import { DataThread } from './DataThread';
4040

src/views/DataThread.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,10 @@ let SingleThreadView: FC<{
189189
<Box sx={{ margin: '4px 8px 4px 2px' }}>
190190
<Typography fontSize="inherit" sx={{
191191
textAlign: 'center',
192-
color: 'rgba(0,0,0,0.7)', maxWidth: 'calc(100%)'
192+
color: 'rgba(0,0,0,0.7)',
193+
maxWidth: '100px',
194+
wordWrap: 'break-word',
195+
whiteSpace: 'normal'
193196
}}>{tableId}</Typography>
194197
</Box>
195198
</Stack>
@@ -495,7 +498,7 @@ export const DataThread: FC<{}> = function ({ }) {
495498
transition: 'width 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms', overflow: 'auto',
496499
direction: 'rtl', display: 'flex', flex: 1
497500
}}
498-
width={drawerOpen ? threadDrawerWidth + 2 : 212} className="thread-view-mode">
501+
width={drawerOpen ? threadDrawerWidth + 12 : 224} className="thread-view-mode">
499502
{view}
500503
</Box>
501504
</Box>

src/views/TableSelectionView.tsx

Lines changed: 38 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import CancelIcon from '@mui/icons-material/Cancel';
2929

3030
import ReactDiffViewer from 'react-diff-viewer'
3131

32-
import { dfActions, dfSelectors, fetchFieldSemanticType } from '../app/dfSlice';
32+
import { DataFormulatorState, dfActions, dfSelectors, fetchFieldSemanticType } from '../app/dfSlice';
3333
import { useDispatch, useSelector } from 'react-redux';
3434
import { useState } from 'react';
3535
import { AppDispatch } from '../app/store';
@@ -254,24 +254,40 @@ export interface TableUploadDialogProps {
254254
disabled: boolean;
255255
}
256256

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+
257267
export const TableUploadDialog: React.FC<TableUploadDialogProps> = ({ buttonElement, disabled }) => {
258268
const dispatch = useDispatch<AppDispatch>();
259269
const inputRef = React.useRef<HTMLInputElement>(null);
270+
const existingTables = useSelector((state: DataFormulatorState) => state.tables);
271+
const existingNames = new Set(existingTables.map(t => t.id));
260272

261273
let handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>): void => {
262274
const files = event.target.files;
263-
275+
264276
if (files) {
265277
for (let file of files) {
266278
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);
268281
if (table) {
269282
dispatch(dfActions.addTable(table));
270283
dispatch(fetchFieldSemanticType(table));
271284
}
272285
});
273286
}
274287
}
288+
if (inputRef.current) {
289+
inputRef.current.value = '';
290+
}
275291
};
276292

277293
return (
@@ -306,72 +322,6 @@ export interface TableCopyDialogProps {
306322
disabled: boolean;
307323
}
308324

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-
375325
export interface TableURLDialogProps {
376326
buttonElement: any;
377327
disabled: boolean;
@@ -473,14 +423,30 @@ export const TableCopyDialogV2: React.FC<TableCopyDialogProps> = ({ buttonElemen
473423
let theme = useTheme()
474424

475425
const dispatch = useDispatch<AppDispatch>();
426+
const existingTables = useSelector((state: DataFormulatorState) => state.tables);
427+
const existingNames = new Set(existingTables.map(t => t.id));
476428

477429
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+
479445
try {
480446
let content = JSON.parse(tableStr);
481-
table = createTableFromFromObjectArray(tableName || 'data-0', content);
447+
table = createTableFromFromObjectArray(uniqueName, content);
482448
} catch (error) {
483-
table = createTableFromText(tableName || 'data-0', tableStr);
449+
table = createTableFromText(uniqueName, tableStr);
484450
}
485451
if (table) {
486452
dispatch(dfActions.addTable(table));

0 commit comments

Comments
 (0)