import type { FC } from 'react' import type { CreateExternalAPIReq, FormSchema } from '../declarations' import { AlertDialog, AlertDialogActions, AlertDialogCancelButton, AlertDialogConfirmButton, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, } from '@langgenius/dify-ui/alert-dialog' import { Button } from '@langgenius/dify-ui/button' import { Dialog, DialogContent, DialogTitle } from '@langgenius/dify-ui/dialog' import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover' import { toast } from '@langgenius/dify-ui/toast' import { RiBook2Line, RiCloseLine, RiInformation2Line, RiLock2Fill } from '@remixicon/react' import { memo, useState } from 'react' import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' import { createExternalAPI } from '@/service/datasets' import Form from './Form' type AddExternalAPIModalProps = { data?: CreateExternalAPIReq onSave: (formValue: CreateExternalAPIReq) => void onCancel: () => void onEdit?: (formValue: CreateExternalAPIReq) => Promise datasetBindings?: { id: string name: string }[] isEditMode: boolean } const formSchemas: FormSchema[] = [ { variable: 'name', type: 'text', label: { en_US: 'Name', }, required: true, }, { variable: 'endpoint', type: 'text', label: { en_US: 'API Endpoint', }, required: true, }, { variable: 'api_key', type: 'secret', label: { en_US: 'API Key', }, required: true, }, ] const emptyExternalAPIFormData: CreateExternalAPIReq = { name: '', settings: { endpoint: '', api_key: '', }, } const AddExternalAPIModal: FC = ({ data, onSave, onCancel, datasetBindings, isEditMode, onEdit }) => { const { t } = useTranslation() const [loading, setLoading] = useState(false) const [showConfirm, setShowConfirm] = useState(false) const [formData, setFormData] = useState(() => isEditMode && data ? data : emptyExternalAPIFormData) const hasEmptyInputs = Object.values(formData).some(value => typeof value === 'string' ? value.trim() === '' : Object.values(value).some(v => v.trim() === '')) const handleDataChange = (val: CreateExternalAPIReq) => { setFormData(val) } const handleSave = async () => { if (formData && formData.settings.api_key && formData.settings.api_key?.length < 5) { toast.error(t('apiBasedExtension.modal.apiKey.lengthError', { ns: 'common' })) setLoading(false) return } try { setLoading(true) if (isEditMode && onEdit) { // Only send [__HIDDEN__] when the user has not changed the key, otherwise // send the actual api_key so updated tokens are persisted. const apiKeyToSend = formData.settings.api_key === '[__HIDDEN__]' ? '[__HIDDEN__]' : formData.settings.api_key await onEdit({ ...formData, settings: { ...formData.settings, api_key: apiKeyToSend }, }) toast.success('External API updated successfully') } else { const res = await createExternalAPI({ body: formData }) if (res && res.id) { toast.success('External API saved successfully') onSave(res) } } onCancel() } catch (error) { console.error('Error saving/updating external API:', error) toast.error('Failed to save/update External API') } finally { setLoading(false) } } return ( { if (!open) onCancel() }} >
{isEditMode ? t('editExternalAPIFormTitle', { ns: 'dataset' }) : t('createExternalAPI', { ns: 'dataset' })} {isEditMode && (datasetBindings?.length ?? 0) > 0 && (
{t('editExternalAPIFormWarning.front', { ns: 'dataset' })}   {datasetBindings?.length} {' '} {t('editExternalAPIFormWarning.end', { ns: 'dataset' })}   )} />
{`${datasetBindings?.length} ${t('editExternalAPITooltipTitle', { ns: 'dataset' })}`}
{datasetBindings?.map(binding => (
{binding.name}
))}
)}
{t('externalAPIForm.encrypted.front', { ns: 'dataset' })} PKCS1_OAEP {t('externalAPIForm.encrypted.end', { ns: 'dataset' })}
0} onOpenChange={open => !open && setShowConfirm(false)} >
Warning {`${t('editExternalAPIConfirmWarningContent.front', { ns: 'dataset' })} ${datasetBindings?.length} ${t('editExternalAPIConfirmWarningContent.end', { ns: 'dataset' })}`}
{t('operation.cancel', { ns: 'common' })} {t('operation.confirm', { ns: 'common' })}
) } export default memo(AddExternalAPIModal)