| 
									
										
										
										
											2025-04-07 06:43:23 +02:00
										 |  |  | '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 { WatercrawlConfig } from '@/models/common' | 
					
						
							|  |  |  | import Field from '@/app/components/datasets/create/website/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.watercrawl' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const DEFAULT_BASE_URL = 'https://app.watercrawl.dev' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ConfigWatercrawlModal: FC<Props> = ({ | 
					
						
							|  |  |  |   onCancel, | 
					
						
							|  |  |  |   onSaved, | 
					
						
							|  |  |  | }) => { | 
					
						
							|  |  |  |   const { t } = useTranslation() | 
					
						
							|  |  |  |   const [isSaving, setIsSaving] = useState(false) | 
					
						
							|  |  |  |   const [config, setConfig] = useState<WatercrawlConfig>({ | 
					
						
							|  |  |  |     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', | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (errorMsg) { | 
					
						
							|  |  |  |       Toast.notify({ | 
					
						
							|  |  |  |         type: 'error', | 
					
						
							|  |  |  |         message: errorMsg, | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const postData = { | 
					
						
							|  |  |  |       category: 'website', | 
					
						
							|  |  |  |       provider: 'watercrawl', | 
					
						
							|  |  |  |       credentials: { | 
					
						
							|  |  |  |         auth_type: 'x-api-key', | 
					
						
							|  |  |  |         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> | 
					
						
							| 
									
										
										
										
											2025-04-11 17:04:06 +08:00
										 |  |  |       <PortalToFollowElemContent className='z-[60] h-full w-full'> | 
					
						
							| 
									
										
										
										
											2025-04-07 06:43:23 +02:00
										 |  |  |         <div className='fixed inset-0 flex items-center justify-center bg-background-overlay'> | 
					
						
							| 
									
										
										
										
											2025-04-11 17:04:06 +08:00
										 |  |  |           <div className='mx-2 max-h-[calc(100vh-120px)] w-[640px] overflow-y-auto rounded-2xl bg-components-panel-bg shadow-xl'> | 
					
						
							| 
									
										
										
										
											2025-04-07 06:43:23 +02:00
										 |  |  |             <div className='px-8 pt-8'> | 
					
						
							| 
									
										
										
										
											2025-04-11 17:04:06 +08:00
										 |  |  |               <div className='mb-4 flex items-center justify-between'> | 
					
						
							| 
									
										
										
										
											2025-04-07 06:43:23 +02:00
										 |  |  |                 <div className='system-xl-semibold text-text-primary'>{t(`${I18N_PREFIX}.configWatercrawl`)}</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> | 
					
						
							| 
									
										
										
										
											2025-04-11 17:04:06 +08:00
										 |  |  |               <div className='my-8 flex h-8 items-center justify-between'> | 
					
						
							|  |  |  |                 <a className='flex items-center space-x-1 text-xs font-normal leading-[18px] text-text-accent' target='_blank' href='https://app.watercrawl.dev/'> | 
					
						
							| 
									
										
										
										
											2025-04-07 06:43:23 +02:00
										 |  |  |                   <span>{t(`${I18N_PREFIX}.getApiKeyLinkText`)}</span> | 
					
						
							| 
									
										
										
										
											2025-04-11 17:04:06 +08:00
										 |  |  |                   <LinkExternal02 className='h-3 w-3' /> | 
					
						
							| 
									
										
										
										
											2025-04-07 06:43:23 +02:00
										 |  |  |                 </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-divider-regular'> | 
					
						
							| 
									
										
										
										
											2025-04-11 17:04:06 +08:00
										 |  |  |               <div className='flex items-center justify-center bg-background-section-burn py-3 text-xs text-text-tertiary'> | 
					
						
							|  |  |  |                 <Lock01 className='mr-1 h-3 w-3 text-text-tertiary' /> | 
					
						
							| 
									
										
										
										
											2025-04-07 06:43:23 +02:00
										 |  |  |                 {t('common.modelProvider.encrypted.front')} | 
					
						
							|  |  |  |                 <a | 
					
						
							| 
									
										
										
										
											2025-04-11 17:04:06 +08:00
										 |  |  |                   className='mx-1 text-text-accent' | 
					
						
							| 
									
										
										
										
											2025-04-07 06:43:23 +02:00
										 |  |  |                   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(ConfigWatercrawlModal) |