mirror of
				https://github.com/langgenius/dify.git
				synced 2025-10-30 18:33:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { useState } from 'react'
 | |
| import Operate from './Operate'
 | |
| import KeyInput from './KeyInput'
 | |
| import { useValidate } from './hooks'
 | |
| import type { Form, KeyFrom, Status, ValidateValue } from './declarations'
 | |
| import { useEventEmitterContextContext } from '@/context/event-emitter'
 | |
| import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general'
 | |
| 
 | |
| export type KeyValidatorProps = {
 | |
|   type: string
 | |
|   title: React.ReactNode
 | |
|   status: Status
 | |
|   forms: Form[]
 | |
|   keyFrom: KeyFrom
 | |
|   onSave: (v: ValidateValue) => Promise<boolean | undefined>
 | |
|   disabled?: boolean
 | |
| }
 | |
| 
 | |
| const KeyValidator = ({
 | |
|   type,
 | |
|   title,
 | |
|   status,
 | |
|   forms,
 | |
|   keyFrom,
 | |
|   onSave,
 | |
|   disabled,
 | |
| }: KeyValidatorProps) => {
 | |
|   const triggerKey = `plugins/${type}`
 | |
|   const { eventEmitter } = useEventEmitterContextContext()
 | |
|   const [isOpen, setIsOpen] = useState(false)
 | |
|   const prevValue = forms.reduce((prev: ValidateValue, next: Form) => {
 | |
|     prev[next.key] = next.value
 | |
|     return prev
 | |
|   }, {})
 | |
|   const [value, setValue] = useState(prevValue)
 | |
|   const [validate, validating, validatedStatusState] = useValidate(value)
 | |
| 
 | |
|   eventEmitter?.useSubscription((v) => {
 | |
|     if (v !== triggerKey) {
 | |
|       setIsOpen(false)
 | |
|       setValue(prevValue)
 | |
|       validate({ before: () => false })
 | |
|     }
 | |
|   })
 | |
| 
 | |
|   const handleCancel = () => {
 | |
|     eventEmitter?.emit('')
 | |
|   }
 | |
| 
 | |
|   const handleSave = async () => {
 | |
|     if (await onSave(value))
 | |
|       eventEmitter?.emit('')
 | |
|   }
 | |
| 
 | |
|   const handleAdd = () => {
 | |
|     setIsOpen(true)
 | |
|     eventEmitter?.emit(triggerKey)
 | |
|   }
 | |
| 
 | |
|   const handleEdit = () => {
 | |
|     setIsOpen(true)
 | |
|     eventEmitter?.emit(triggerKey)
 | |
|   }
 | |
| 
 | |
|   const handleChange = (form: Form, val: string) => {
 | |
|     setValue({ ...value, [form.key]: val })
 | |
| 
 | |
|     if (form.validate)
 | |
|       validate(form.validate)
 | |
|   }
 | |
| 
 | |
|   const handleFocus = (form: Form) => {
 | |
|     if (form.handleFocus)
 | |
|       form.handleFocus(value, setValue)
 | |
|   }
 | |
| 
 | |
|   return (
 | |
|     <div className='mb-2 border-[0.5px] border-gray-200 bg-gray-50 rounded-md'>
 | |
|       <div className={
 | |
|         `flex items-center justify-between px-4 h-[52px] cursor-pointer ${isOpen && 'border-b-[0.5px] border-b-gray-200'}`
 | |
|       }>
 | |
|         {title}
 | |
|         <Operate
 | |
|           isOpen={isOpen}
 | |
|           status={status}
 | |
|           onCancel={handleCancel}
 | |
|           onSave={handleSave}
 | |
|           onAdd={handleAdd}
 | |
|           onEdit={handleEdit}
 | |
|           disabled={disabled}
 | |
|         />
 | |
|       </div>
 | |
|       {
 | |
|         isOpen && !disabled && (
 | |
|           <div className='px-4 py-3'>
 | |
|             {
 | |
|               forms.map(form => (
 | |
|                 <KeyInput
 | |
|                   key={form.key}
 | |
|                   className='mb-4'
 | |
|                   name={form.title}
 | |
|                   placeholder={form.placeholder}
 | |
|                   value={value[form.key] as string || ''}
 | |
|                   onChange={v => handleChange(form, v)}
 | |
|                   onFocus={() => handleFocus(form)}
 | |
|                   validating={validating}
 | |
|                   validatedStatusState={validatedStatusState}
 | |
|                 />
 | |
|               ))
 | |
|             }
 | |
|             <a className="flex items-center text-xs cursor-pointer text-primary-600" href={keyFrom.link} target='_blank' rel='noopener noreferrer'>
 | |
|               {keyFrom.text}
 | |
|               <LinkExternal02 className='w-3 h-3 ml-1 text-primary-600' />
 | |
|             </a>
 | |
|           </div>
 | |
|         )
 | |
|       }
 | |
|     </div>
 | |
|   )
 | |
| }
 | |
| 
 | |
| export default KeyValidator
 | 
