import type { ComponentProps } from 'react' import type { EndpointListItem, PluginDetail } from '../types' import { AlertDialog, AlertDialogActions, AlertDialogCancelButton, AlertDialogConfirmButton, AlertDialogContent, AlertDialogTitle, } from '@langgenius/dify-ui/alert-dialog' import { StatusDot } from '@langgenius/dify-ui/status-dot' import { Switch } from '@langgenius/dify-ui/switch' import { toast } from '@langgenius/dify-ui/toast' import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { useBoolean } from 'ahooks' import copy from 'copy-to-clipboard' import * as React from 'react' import { useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' import { CopyCheck } from '@/app/components/base/icons/src/vender/line/files' import { addDefaultValue, toolCredentialToFormSchemas, } from '@/app/components/tools/utils/to-form-schema' import { useDeleteEndpoint, useDisableEndpoint, useEnableEndpoint, useUpdateEndpoint, } from '@/service/use-endpoints' import EndpointModal from './endpoint-modal' import { NAME_FIELD } from './utils' type EndpointModalFormSchemas = ComponentProps['formSchemas'] type Props = Readonly<{ pluginDetail: PluginDetail data: EndpointListItem handleChange: () => void }> const EndpointCard = ({ pluginDetail, data, handleChange }: Props) => { const { t } = useTranslation() const [active, setActive] = useState(data.enabled) const endpointID = data.id // switch const [isShowDisableConfirm, { setTrue: showDisableConfirm, setFalse: hideDisableConfirm }] = useBoolean(false) const { mutate: enableEndpoint } = useEnableEndpoint({ onSuccess: async () => { await handleChange() }, onError: () => { toast.error(t(($) => $['actionMsg.modifiedUnsuccessfully'], { ns: 'common' })) setActive(false) }, }) const { mutate: disableEndpoint } = useDisableEndpoint({ onSuccess: async () => { await handleChange() hideDisableConfirm() }, onError: () => { toast.error(t(($) => $['actionMsg.modifiedUnsuccessfully'], { ns: 'common' })) setActive(false) }, }) const handleSwitch = (state: boolean) => { if (state) { setActive(true) enableEndpoint(endpointID) } else { setActive(false) showDisableConfirm() } } // delete const [isShowDeleteConfirm, { setTrue: showDeleteConfirm, setFalse: hideDeleteConfirm }] = useBoolean(false) const { mutate: deleteEndpoint } = useDeleteEndpoint({ onSuccess: async () => { await handleChange() hideDeleteConfirm() }, onError: () => { toast.error(t(($) => $['actionMsg.modifiedUnsuccessfully'], { ns: 'common' })) }, }) // update const [ isShowEndpointModal, { setTrue: showEndpointModalConfirm, setFalse: hideEndpointModalConfirm }, ] = useBoolean(false) const formSchemas = useMemo(() => { return toolCredentialToFormSchemas([NAME_FIELD, ...data.declaration.settings]) }, [data.declaration.settings]) const formValue = useMemo(() => { const formValue = { name: data.name, ...data.settings, } return addDefaultValue(formValue, formSchemas) }, [data.name, data.settings, formSchemas]) const { mutate: updateEndpoint } = useUpdateEndpoint({ onSuccess: async () => { await handleChange() hideEndpointModalConfirm() }, onError: () => { toast.error(t(($) => $['actionMsg.modifiedUnsuccessfully'], { ns: 'common' })) }, }) const handleUpdate = (state: Record) => updateEndpoint({ endpointID, state, }) const [isCopied, setIsCopied] = useState(false) const handleCopy = (value: string) => { copy(value) setIsCopied(true) } const handleDisableConfirmOpenChange = (open: boolean) => { if (open) return hideDisableConfirm() setActive(true) } useEffect(() => { if (isCopied) { const timer = setTimeout(() => { setIsCopied(false) }, 2000) return () => { clearTimeout(timer) } } }, [isCopied]) const copyLabel = t(($) => $[`operation.${isCopied ? 'copied' : 'copy'}`], { ns: 'common' }) return (
{data.name}
{(data.declaration.endpoints ?? []) .filter((endpoint) => !endpoint.hidden) .map((endpoint, index) => (
{endpoint.method}
{`${data.url}${endpoint.path}`}
handleCopy(`${data.url}${endpoint.path}`)} > {isCopied ? ( ) : ( )} } /> {copyLabel}
))}
{active && (
{t(($) => $['detailPanel.serviceOk'], { ns: 'plugin' })}
)} {!active && (
{t(($) => $['detailPanel.disabled'], { ns: 'plugin' })}
)}
{t(($) => $['detailPanel.endpointDisableTip'], { ns: 'plugin' })}
{t(($) => $['detailPanel.endpointDisableContent'], { ns: 'plugin', name: data.name })}
{t(($) => $['operation.cancel'], { ns: 'common' })} disableEndpoint(endpointID)}> {t(($) => $['operation.confirm'], { ns: 'common' })}
!open && hideDeleteConfirm()}>
{t(($) => $['detailPanel.endpointDeleteTip'], { ns: 'plugin' })}
{t(($) => $['detailPanel.endpointDeleteContent'], { ns: 'plugin', name: data.name })}
{t(($) => $['operation.cancel'], { ns: 'common' })} deleteEndpoint(endpointID)}> {t(($) => $['operation.confirm'], { ns: 'common' })}
{isShowEndpointModal && ( )}
) } export default EndpointCard