| 
                        123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 | 
                        - 'use client'
 - import type { FC } from 'react'
 - import React, { useCallback, useState } from 'react'
 - import { useTranslation } from 'react-i18next'
 - import {
 -   PortalToFollowElem,
 -   PortalToFollowElemContent,
 - } from '@/app/components/base/portal-to-follow-elem'
 - import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security'
 - import Button from '@/app/components/base/button'
 - import type { FirecrawlConfig } from '@/models/common'
 - import Field from '@/app/components/datasets/create/website/firecrawl/base/field'
 - import Toast from '@/app/components/base/toast'
 - import { createDataSourceApiKeyBinding } from '@/service/datasets'
 - import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general'
 - type Props = {
 -   onCancel: () => void
 -   onSaved: () => void
 - }
 - 
 - const I18N_PREFIX = 'datasetCreation.firecrawl'
 - 
 - const DEFAULT_BASE_URL = 'https://api.firecrawl.dev'
 - 
 - const ConfigFirecrawlModal: FC<Props> = ({
 -   onCancel,
 -   onSaved,
 - }) => {
 -   const { t } = useTranslation()
 -   const [isSaving, setIsSaving] = useState(false)
 -   const [config, setConfig] = useState<FirecrawlConfig>({
 -     api_key: '',
 -     base_url: '',
 -   })
 - 
 -   const handleConfigChange = useCallback((key: string) => {
 -     return (value: string | number) => {
 -       setConfig(prev => ({ ...prev, [key]: value as string }))
 -     }
 -   }, [])
 - 
 -   const handleSave = useCallback(async () => {
 -     if (isSaving)
 -       return
 -     let errorMsg = ''
 -     if (config.base_url && !((config.base_url.startsWith('http://') || config.base_url.startsWith('https://'))))
 -       errorMsg = t('common.errorMsg.urlError')
 -     if (!errorMsg) {
 -       if (!config.api_key) {
 -         errorMsg = t('common.errorMsg.fieldRequired', {
 -           field: 'API Key',
 -         })
 -       }
 -       else if (!config.api_key.startsWith('fc-')) {
 -         errorMsg = t(`${I18N_PREFIX}.apiKeyFormatError`)
 -       }
 -     }
 - 
 -     if (errorMsg) {
 -       Toast.notify({
 -         type: 'error',
 -         message: errorMsg,
 -       })
 -       return
 -     }
 -     const postData = {
 -       category: 'website',
 -       provider: 'firecrawl',
 -       credentials: {
 -         auth_type: 'bearer',
 -         config: {
 -           api_key: config.api_key,
 -           base_url: config.base_url || DEFAULT_BASE_URL,
 -         },
 -       },
 -     }
 -     try {
 -       setIsSaving(true)
 -       await createDataSourceApiKeyBinding(postData)
 -       Toast.notify({
 -         type: 'success',
 -         message: t('common.api.success'),
 -       })
 -     }
 -     finally {
 -       setIsSaving(false)
 -     }
 - 
 -     onSaved()
 -   }, [config.api_key, config.base_url, onSaved, t, isSaving])
 - 
 -   return (
 -     <PortalToFollowElem open>
 -       <PortalToFollowElemContent className='w-full h-full z-[60]'>
 -         <div className='fixed inset-0 flex items-center justify-center bg-black/[.25]'>
 -           <div className='mx-2 w-[640px] max-h-[calc(100vh-120px)] bg-white shadow-xl rounded-2xl overflow-y-auto'>
 -             <div className='px-8 pt-8'>
 -               <div className='flex justify-between items-center mb-4'>
 -                 <div className='text-xl font-semibold text-gray-900'>{t(`${I18N_PREFIX}.configFirecrawl`)}</div>
 -               </div>
 - 
 -               <div className='space-y-4'>
 -                 <Field
 -                   label='API Key'
 -                   labelClassName='!text-sm'
 -                   isRequired
 -                   value={config.api_key}
 -                   onChange={handleConfigChange('api_key')}
 -                   placeholder={t(`${I18N_PREFIX}.apiKeyPlaceholder`)!}
 -                 />
 -                 <Field
 -                   label='Base URL'
 -                   labelClassName='!text-sm'
 -                   value={config.base_url}
 -                   onChange={handleConfigChange('base_url')}
 -                   placeholder={DEFAULT_BASE_URL}
 -                 />
 -               </div>
 -               <div className='my-8 flex justify-between items-center h-8'>
 -                 <a className='flex items-center space-x-1 leading-[18px] text-xs font-normal text-[#155EEF]' target='_blank' href='https://www.firecrawl.dev/account'>
 -                   <span>{t(`${I18N_PREFIX}.getApiKeyLinkText`)}</span>
 -                   <LinkExternal02 className='w-3 h-3' />
 -                 </a>
 -                 <div className='flex'>
 -                   <Button
 -                     size='large'
 -                     className='mr-2'
 -                     onClick={onCancel}
 -                   >
 -                     {t('common.operation.cancel')}
 -                   </Button>
 -                   <Button
 -                     variant='primary'
 -                     size='large'
 -                     onClick={handleSave}
 -                     loading={isSaving}
 -                   >
 -                     {t('common.operation.save')}
 -                   </Button>
 -                 </div>
 - 
 -               </div>
 -             </div>
 -             <div className='border-t-[0.5px] border-t-black/5'>
 -               <div className='flex justify-center items-center py-3 bg-gray-50 text-xs text-gray-500'>
 -                 <Lock01 className='mr-1 w-3 h-3 text-gray-500' />
 -                 {t('common.modelProvider.encrypted.front')}
 -                 <a
 -                   className='text-primary-600 mx-1'
 -                   target='_blank' rel='noopener noreferrer'
 -                   href='https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html'
 -                 >
 -                   PKCS1_OAEP
 -                 </a>
 -                 {t('common.modelProvider.encrypted.back')}
 -               </div>
 -             </div>
 -           </div>
 -         </div>
 -       </PortalToFollowElemContent>
 -     </PortalToFollowElem>
 -   )
 - }
 - export default React.memo(ConfigFirecrawlModal)
 
 
  |