|
'use client' |
|
import type { FC } from 'react' |
|
import React, { useState } from 'react' |
|
import { useTranslation } from 'react-i18next' |
|
import { useClickAway } from 'ahooks' |
|
import { |
|
RiAddLine, |
|
RiArrowDownSLine, |
|
} from '@remixicon/react' |
|
import Toast from '../../base/toast' |
|
import examples from './examples' |
|
import Button from '@/app/components/base/button' |
|
import { importSchemaFromURL } from '@/service/tools' |
|
|
|
type Props = { |
|
onChange: (value: string) => void |
|
} |
|
|
|
const GetSchema: FC<Props> = ({ |
|
onChange, |
|
}) => { |
|
const { t } = useTranslation() |
|
const [showImportFromUrl, setShowImportFromUrl] = useState(false) |
|
const [importUrl, setImportUrl] = useState('') |
|
const [isParsing, setIsParsing] = useState(false) |
|
const handleImportFromUrl = async () => { |
|
if (!importUrl.startsWith('http://') && !importUrl.startsWith('https://')) { |
|
Toast.notify({ |
|
type: 'error', |
|
message: t('tools.createTool.urlError'), |
|
}) |
|
return |
|
} |
|
setIsParsing(true) |
|
try { |
|
const { schema } = await importSchemaFromURL(importUrl) as any |
|
setImportUrl('') |
|
onChange(schema) |
|
} |
|
finally { |
|
setIsParsing(false) |
|
setShowImportFromUrl(false) |
|
} |
|
} |
|
|
|
const importURLRef = React.useRef(null) |
|
useClickAway(() => { |
|
setShowImportFromUrl(false) |
|
}, importURLRef) |
|
|
|
const [showExamples, setShowExamples] = useState(false) |
|
const showExamplesRef = React.useRef(null) |
|
useClickAway(() => { |
|
setShowExamples(false) |
|
}, showExamplesRef) |
|
|
|
return ( |
|
<div className='flex space-x-1 justify-end relative w-[224px]'> |
|
<div ref={importURLRef}> |
|
<Button |
|
size='small' |
|
className='space-x-1 ' |
|
onClick={() => { setShowImportFromUrl(!showImportFromUrl) }} |
|
> |
|
<RiAddLine className='w-3 h-3' /> |
|
<div className='text-xs font-medium text-gray-700'>{t('tools.createTool.importFromUrl')}</div> |
|
</Button> |
|
{showImportFromUrl && ( |
|
<div className=' absolute left-[-35px] top-[26px] p-2 rounded-lg border border-gray-200 bg-white shadow-lg'> |
|
<div className='relative'> |
|
<input |
|
type='text' |
|
className='w-[244px] h-8 pl-1.5 pr-[44px] overflow-x-auto border border-gray-200 rounded-lg text-[13px]' |
|
placeholder={t('tools.createTool.importFromUrlPlaceHolder')!} |
|
value={importUrl} |
|
onChange={e => setImportUrl(e.target.value)} |
|
/> |
|
<Button |
|
className='absolute top-1 right-1' |
|
size='small' |
|
variant='primary' |
|
disabled={!importUrl} |
|
onClick={handleImportFromUrl} |
|
loading={isParsing} |
|
> |
|
{isParsing ? '' : t('common.operation.ok')} |
|
</Button> |
|
</div> |
|
</div> |
|
)} |
|
</div> |
|
<div className='relative' ref={showExamplesRef}> |
|
<Button |
|
size='small' |
|
className='space-x-1' |
|
onClick={() => { setShowExamples(!showExamples) }} |
|
> |
|
<div className='text-xs font-medium text-gray-700'>{t('tools.createTool.examples')}</div> |
|
<RiArrowDownSLine className='w-3 h-3' /> |
|
</Button> |
|
{showExamples && ( |
|
<div className='absolute top-7 right-0 p-1 rounded-lg bg-white shadow-sm'> |
|
{examples.map(item => ( |
|
<div |
|
key={item.key} |
|
onClick={() => { |
|
onChange(item.content) |
|
setShowExamples(false) |
|
}} |
|
className='px-3 py-1.5 rounded-lg hover:bg-gray-50 leading-5 text-sm font-normal text-gray-700 cursor-pointer whitespace-nowrap' |
|
> |
|
{t(`tools.createTool.exampleOptions.${item.key}`)} |
|
</div> |
|
))} |
|
</div> |
|
)} |
|
|
|
</div> |
|
</div> |
|
) |
|
} |
|
export default React.memo(GetSchema) |
|
|