get-schema.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useState } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import { useClickAway } from 'ahooks'
  6. import {
  7. RiAddLine,
  8. RiArrowDownSLine,
  9. } from '@remixicon/react'
  10. import Toast from '../../base/toast'
  11. import examples from './examples'
  12. import Button from '@/app/components/base/button'
  13. import { importSchemaFromURL } from '@/service/tools'
  14. type Props = {
  15. onChange: (value: string) => void
  16. }
  17. const GetSchema: FC<Props> = ({
  18. onChange,
  19. }) => {
  20. const { t } = useTranslation()
  21. const [showImportFromUrl, setShowImportFromUrl] = useState(false)
  22. const [importUrl, setImportUrl] = useState('')
  23. const [isParsing, setIsParsing] = useState(false)
  24. const handleImportFromUrl = async () => {
  25. if (!importUrl.startsWith('http://') && !importUrl.startsWith('https://')) {
  26. Toast.notify({
  27. type: 'error',
  28. message: t('tools.createTool.urlError'),
  29. })
  30. return
  31. }
  32. setIsParsing(true)
  33. try {
  34. const { schema } = await importSchemaFromURL(importUrl) as any
  35. setImportUrl('')
  36. onChange(schema)
  37. }
  38. finally {
  39. setIsParsing(false)
  40. setShowImportFromUrl(false)
  41. }
  42. }
  43. const importURLRef = React.useRef(null)
  44. useClickAway(() => {
  45. setShowImportFromUrl(false)
  46. }, importURLRef)
  47. const [showExamples, setShowExamples] = useState(false)
  48. const showExamplesRef = React.useRef(null)
  49. useClickAway(() => {
  50. setShowExamples(false)
  51. }, showExamplesRef)
  52. return (
  53. <div className='flex space-x-1 justify-end relative w-[224px]'>
  54. <div ref={importURLRef}>
  55. <Button
  56. size='small'
  57. className='space-x-1 '
  58. onClick={() => { setShowImportFromUrl(!showImportFromUrl) }}
  59. >
  60. <RiAddLine className='w-3 h-3' />
  61. <div className='text-xs font-medium text-gray-700'>{t('tools.createTool.importFromUrl')}</div>
  62. </Button>
  63. {showImportFromUrl && (
  64. <div className=' absolute left-[-35px] top-[26px] p-2 rounded-lg border border-gray-200 bg-white shadow-lg'>
  65. <div className='relative'>
  66. <input
  67. type='text'
  68. className='w-[244px] h-8 pl-1.5 pr-[44px] overflow-x-auto border border-gray-200 rounded-lg text-[13px] focus:outline-none focus:border-components-input-border-active'
  69. placeholder={t('tools.createTool.importFromUrlPlaceHolder')!}
  70. value={importUrl}
  71. onChange={e => setImportUrl(e.target.value)}
  72. />
  73. <Button
  74. className='absolute top-1 right-1'
  75. size='small'
  76. variant='primary'
  77. disabled={!importUrl}
  78. onClick={handleImportFromUrl}
  79. loading={isParsing}
  80. >
  81. {isParsing ? '' : t('common.operation.ok')}
  82. </Button>
  83. </div>
  84. </div>
  85. )}
  86. </div>
  87. <div className='relative -mt-0.5' ref={showExamplesRef}>
  88. <Button
  89. size='small'
  90. className='space-x-1'
  91. onClick={() => { setShowExamples(!showExamples) }}
  92. >
  93. <div className='text-xs font-medium text-gray-700'>{t('tools.createTool.examples')}</div>
  94. <RiArrowDownSLine className='w-3 h-3' />
  95. </Button>
  96. {showExamples && (
  97. <div className='absolute top-7 right-0 p-1 rounded-lg bg-white shadow-sm'>
  98. {examples.map(item => (
  99. <div
  100. key={item.key}
  101. onClick={() => {
  102. onChange(item.content)
  103. setShowExamples(false)
  104. }}
  105. 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'
  106. >
  107. {t(`tools.createTool.exampleOptions.${item.key}`)}
  108. </div>
  109. ))}
  110. </div>
  111. )}
  112. </div>
  113. </div>
  114. )
  115. }
  116. export default React.memo(GetSchema)