feat: add SchemaEditor component and integrate it into JSON Schema config modal
This commit is contained in:
parent
a07831bc05
commit
183edf0fd5
@ -9,6 +9,7 @@ import JsonImporter from './json-importer'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import VisualEditor from './visual-editor'
|
||||
import SchemaEditor from './schema-editor'
|
||||
|
||||
type JsonSchemaConfigModalProps = {
|
||||
isShow: boolean
|
||||
@ -43,6 +44,7 @@ const JsonSchemaConfigModal: FC<JsonSchemaConfigModalProps> = ({
|
||||
const { t } = useTranslation()
|
||||
const [currentTab, setCurrentTab] = useState(SchemaView.VisualEditor)
|
||||
const [jsonSchema, setJsonSchema] = useState(defaultSchema || DEFAULT_SCHEMA)
|
||||
const [json, setJson] = useState(JSON.stringify(jsonSchema, null, 2))
|
||||
const [btnWidth, setBtnWidth] = useState(0)
|
||||
|
||||
const updateBtnWidth = useCallback((width: number) => {
|
||||
@ -57,6 +59,10 @@ const JsonSchemaConfigModal: FC<JsonSchemaConfigModalProps> = ({
|
||||
setJsonSchema(schema)
|
||||
}, [])
|
||||
|
||||
const handleSchemaEditorUpdate = useCallback((schema: string) => {
|
||||
setJson(schema)
|
||||
}, [])
|
||||
|
||||
const handleResetDefaults = useCallback(() => {
|
||||
setJsonSchema(defaultSchema || DEFAULT_SCHEMA)
|
||||
}, [defaultSchema])
|
||||
@ -118,7 +124,10 @@ const JsonSchemaConfigModal: FC<JsonSchemaConfigModalProps> = ({
|
||||
/>
|
||||
)}
|
||||
{currentTab === SchemaView.JsonSchema && (
|
||||
<div className='h-full rounded-xl bg-components-input-bg-normal'>JSON Schema</div>
|
||||
<SchemaEditor
|
||||
schema={json}
|
||||
onUpdate={handleSchemaEditorUpdate}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{/* Footer */}
|
||||
|
||||
@ -166,7 +166,6 @@ const JsonImporter: FC<JsonImporterProps> = ({
|
||||
alwaysConsumeMouseWheel: false,
|
||||
},
|
||||
}}
|
||||
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -131,7 +131,6 @@ const GeneratedResult: FC<GeneratedResultProps> = ({
|
||||
alwaysConsumeMouseWheel: false,
|
||||
},
|
||||
}}
|
||||
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,102 @@
|
||||
import { Editor } from '@monaco-editor/react'
|
||||
import { RiClipboardLine, RiIndentIncrease } from '@remixicon/react'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import React, { type FC, useCallback, useRef } from 'react'
|
||||
|
||||
type SchemaEditorProps = {
|
||||
schema: string
|
||||
onUpdate: (schema: string) => void
|
||||
}
|
||||
|
||||
const SchemaEditor: FC<SchemaEditorProps> = ({
|
||||
schema,
|
||||
onUpdate,
|
||||
}) => {
|
||||
const monacoRef = useRef<any>(null)
|
||||
const editorRef = useRef<any>(null)
|
||||
|
||||
const handleEditorDidMount = useCallback((editor: any, monaco: any) => {
|
||||
editorRef.current = editor
|
||||
monacoRef.current = monaco
|
||||
monaco.editor.defineTheme('light-theme', {
|
||||
base: 'vs',
|
||||
inherit: true,
|
||||
rules: [],
|
||||
colors: {
|
||||
'editor.background': '#00000000',
|
||||
'editor.lineHighlightBackground': '#00000000',
|
||||
'focusBorder': '#00000000',
|
||||
},
|
||||
})
|
||||
monaco.editor.setTheme('light-theme')
|
||||
}, [])
|
||||
|
||||
const formatJsonContent = useCallback(() => {
|
||||
if (editorRef.current)
|
||||
editorRef.current.getAction('editor.action.formatDocument')?.run()
|
||||
}, [])
|
||||
|
||||
const handleEditorChange = useCallback((value: string | undefined) => {
|
||||
if (!value)
|
||||
return
|
||||
onUpdate(value)
|
||||
}, [onUpdate])
|
||||
|
||||
return (
|
||||
<div className='flex flex-col h-full rounded-xl bg-components-input-bg-normal overflow-hidden'>
|
||||
<div className='flex items-center justify-between pl-2 pt-1 pr-1'>
|
||||
<div className='py-0.5 text-text-secondary system-xs-semibold-uppercase'>
|
||||
<span className='px-1 py-0.5'>JSON</span>
|
||||
</div>
|
||||
<div className='flex items-center gap-x-0.5'>
|
||||
<button
|
||||
type='button'
|
||||
className='flex items-center justify-center h-6 w-6'
|
||||
onClick={formatJsonContent}
|
||||
>
|
||||
<RiIndentIncrease className='w-4 h-4 text-text-tertiary' />
|
||||
</button>
|
||||
<button
|
||||
type='button'
|
||||
className='flex items-center justify-center h-6 w-6'
|
||||
onClick={() => copy(schema)}>
|
||||
<RiClipboardLine className='w-4 h-4 text-text-tertiary' />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className='relative grow'>
|
||||
<Editor
|
||||
height='100%'
|
||||
defaultLanguage='json'
|
||||
value={schema}
|
||||
onChange={handleEditorChange}
|
||||
onMount={handleEditorDidMount}
|
||||
options={{
|
||||
readOnly: false,
|
||||
domReadOnly: true,
|
||||
minimap: { enabled: false },
|
||||
tabSize: 2,
|
||||
scrollBeyondLastLine: false,
|
||||
wordWrap: 'on',
|
||||
wrappingIndent: 'same',
|
||||
// Add these options
|
||||
overviewRulerBorder: false,
|
||||
hideCursorInOverviewRuler: true,
|
||||
renderLineHighlightOnlyWhenFocus: false,
|
||||
renderLineHighlight: 'none',
|
||||
// Hide scrollbar borders
|
||||
scrollbar: {
|
||||
vertical: 'hidden',
|
||||
horizontal: 'hidden',
|
||||
verticalScrollbarSize: 0,
|
||||
horizontalScrollbarSize: 0,
|
||||
alwaysConsumeMouseWheel: false,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SchemaEditor
|
||||
@ -0,0 +1,31 @@
|
||||
import { type FC, useState } from 'react'
|
||||
import type { Field } from '../../../types'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { RiAddCircleFill } from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
type AddToRootProps = {
|
||||
addField: (path: string[], updates: Field) => void
|
||||
}
|
||||
|
||||
const AddField: FC<AddToRootProps> = ({
|
||||
addField,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const [isEditing, setIsEditing] = useState(false)
|
||||
|
||||
const handleAddField = () => {
|
||||
setIsEditing(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button size='small' className='flex items-center gap-x-[1px]' onClick={handleAddField}>
|
||||
<RiAddCircleFill className='w-3.5 h-3.5'/>
|
||||
<span className='px-[3px]'>{t('workflow.nodes.llm.jsonSchema.addField')}</span>
|
||||
</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddField
|
||||
Loading…
x
Reference in New Issue
Block a user