Skip to content

Commit 66d6c01

Browse files
committed
feat: add paste JSON schema functionality to custom tools
- Add PasteJSONDialog component for JSON input - Add Paste JSON button to Tool Dialog - Support JSON validation and format conversion - Add example JSON template
1 parent c0a7478 commit 66d6c01

File tree

2 files changed

+113
-4
lines changed

2 files changed

+113
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { createPortal } from 'react-dom'
2+
import PropTypes from 'prop-types'
3+
import { useState } from 'react'
4+
import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material'
5+
import { StyledButton } from '@/ui-component/button/StyledButton'
6+
import { CodeEditor } from '@/ui-component/editor/CodeEditor'
7+
8+
const PasteJSONDialog = ({ show, onCancel, onConfirm, customization }) => {
9+
const portalElement = document.getElementById('portal')
10+
const [jsonInput, setJsonInput] = useState('')
11+
const [error, setError] = useState('')
12+
13+
const handleConfirm = () => {
14+
try {
15+
const parsedJSON = JSON.parse(jsonInput)
16+
if (!Array.isArray(parsedJSON)) throw new Error('Input must be an array of properties')
17+
const formattedData = parsedJSON.map((item, index) => ({
18+
id: index + 1,
19+
property: item.property || '',
20+
type: item.type || 'string',
21+
description: item.description || '',
22+
required: item.required || false
23+
}))
24+
onConfirm(formattedData)
25+
setError('')
26+
} catch (err) {
27+
setError('Invalid JSON format. Please check your input.')
28+
}
29+
}
30+
31+
const exampleJSON = `[
32+
{
33+
"property": "name",
34+
"type": "string",
35+
"description": "User's name",
36+
"required": true
37+
},
38+
{
39+
"property": "age",
40+
"type": "number",
41+
"description": "User's age",
42+
"required": false
43+
}
44+
]`
45+
46+
const component = show ? (
47+
<Dialog fullWidth maxWidth='md' open={show} onClose={onCancel} aria-labelledby='paste-json-dialog-title'>
48+
<DialogTitle sx={{ fontSize: '1rem' }} id='paste-json-dialog-title'>
49+
Paste JSON Schema
50+
</DialogTitle>
51+
<DialogContent>
52+
<Box sx={{ mt: 2 }}>
53+
<Button variant='outlined' size='small' onClick={() => setJsonInput(exampleJSON)} sx={{ mb: 2 }}>
54+
See Example
55+
</Button>
56+
<CodeEditor
57+
value={jsonInput}
58+
theme={customization.isDarkMode ? 'dark' : 'light'}
59+
lang='json'
60+
onValueChange={(code) => {
61+
setJsonInput(code)
62+
setError('')
63+
}}
64+
/>
65+
{error && <Box sx={{ color: 'error.main', mt: 1, fontSize: '0.875rem' }}>{error}</Box>}
66+
</Box>
67+
</DialogContent>
68+
<DialogActions>
69+
<Button onClick={onCancel}>Cancel</Button>
70+
<StyledButton variant='contained' onClick={handleConfirm}>
71+
Confirm
72+
</StyledButton>
73+
</DialogActions>
74+
</Dialog>
75+
) : null
76+
77+
return createPortal(component, portalElement)
78+
}
79+
80+
PasteJSONDialog.propTypes = {
81+
show: PropTypes.bool,
82+
onCancel: PropTypes.func,
83+
onConfirm: PropTypes.func,
84+
customization: PropTypes.object
85+
}
86+
87+
export default PasteJSONDialog

packages/ui/src/views/tools/ToolDialog.jsx

+26-4
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ import DeleteIcon from '@mui/icons-material/Delete'
1414
import ConfirmDialog from '@/ui-component/dialog/ConfirmDialog'
1515
import { CodeEditor } from '@/ui-component/editor/CodeEditor'
1616
import HowToUseFunctionDialog from './HowToUseFunctionDialog'
17+
import PasteJSONDialog from './PasteJSONDialog'
1718

1819
// Icons
19-
import { IconX, IconFileDownload, IconPlus, IconTemplate } from '@tabler/icons-react'
20+
import { IconX, IconFileDownload, IconPlus, IconTemplate, IconCode } from '@tabler/icons-react'
2021

2122
// API
2223
import toolsApi from '@/api/tools'
@@ -83,6 +84,8 @@ const ToolDialog = ({ show, dialogProps, onUseTemplate, onCancel, onConfirm, set
8384
const [exportAsTemplateDialogOpen, setExportAsTemplateDialogOpen] = useState(false)
8485
const [exportAsTemplateDialogProps, setExportAsTemplateDialogProps] = useState({})
8586

87+
const [showPasteJSONDialog, setShowPasteJSONDialog] = useState(false)
88+
8689
const deleteItem = useCallback(
8790
(id) => () => {
8891
setTimeout(() => {
@@ -409,6 +412,11 @@ const ToolDialog = ({ show, dialogProps, onUseTemplate, onCancel, onConfirm, set
409412
}
410413
}
411414

415+
const handlePastedJSON = (formattedData) => {
416+
setToolSchema(formattedData)
417+
setShowPasteJSONDialog(false)
418+
}
419+
412420
const component = show ? (
413421
<Dialog
414422
fullWidth
@@ -507,9 +515,14 @@ const ToolDialog = ({ show, dialogProps, onUseTemplate, onCancel, onConfirm, set
507515
<TooltipWithParser title={'What is the input format in JSON?'} />
508516
</Stack>
509517
{dialogProps.type !== 'TEMPLATE' && (
510-
<Button variant='outlined' onClick={addNewRow} startIcon={<IconPlus />}>
511-
Add Item
512-
</Button>
518+
<Stack direction='row' spacing={1}>
519+
<Button variant='outlined' onClick={() => setShowPasteJSONDialog(true)} startIcon={<IconCode />}>
520+
Paste JSON
521+
</Button>
522+
<Button variant='outlined' onClick={addNewRow} startIcon={<IconPlus />}>
523+
Add Item
524+
</Button>
525+
</Stack>
513526
)}
514527
</Stack>
515528
<Grid columns={columns} rows={toolSchema} disabled={dialogProps.type === 'TEMPLATE'} onRowUpdate={onRowUpdate} />
@@ -577,6 +590,15 @@ const ToolDialog = ({ show, dialogProps, onUseTemplate, onCancel, onConfirm, set
577590
)}
578591

579592
<HowToUseFunctionDialog show={showHowToDialog} onCancel={() => setShowHowToDialog(false)} />
593+
594+
{showPasteJSONDialog && (
595+
<PasteJSONDialog
596+
show={showPasteJSONDialog}
597+
onCancel={() => setShowPasteJSONDialog(false)}
598+
onConfirm={handlePastedJSON}
599+
customization={customization}
600+
/>
601+
)}
580602
</Dialog>
581603
) : null
582604

0 commit comments

Comments
 (0)