diff --git a/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx b/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx index 5e70ca1efa..72f89d8194 100644 --- a/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx +++ b/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx @@ -1,12 +1,16 @@ import React, { useState } from 'react' import { useTranslation } from 'react-i18next' +import { useBoolean } from 'ahooks' import { RiDeleteBinLine, RiEditLine, RiLoginCircleLine } from '@remixicon/react' import type { EndpointListItem } from '../types' +import EndpointModal from './endpoint-modal' import ActionButton from '@/app/components/base/action-button' import CopyBtn from '@/app/components/base/copy-btn' +import Confirm from '@/app/components/base/confirm' import Indicator from '@/app/components/header/indicator' import Switch from '@/app/components/base/switch' import { + deleteEndpoint, disableEndpoint, enableEndpoint, } from '@/service/plugins' @@ -22,6 +26,10 @@ const EndpointCard = ({ const [active, setActive] = useState(data.enabled) const endpointID = data.id + const [isShowDisableConfirm, { + setTrue: showDisableConfirm, + setFalse: hideDisableConfirm, + }] = useBoolean(false) const activeEndpoint = async () => { try { await enableEndpoint({ @@ -31,7 +39,7 @@ const EndpointCard = ({ } catch (error) { console.error(error) - setActive(true) + setActive(false) } } const inactiveEndpoint = async () => { @@ -43,16 +51,41 @@ const EndpointCard = ({ } catch (error) { console.error(error) - setActive(false) + setActive(true) } } const handleSwitch = (state: boolean) => { - if (state) + if (state) { + setActive(true) activeEndpoint() - else - inactiveEndpoint() + } + else { + setActive(false) + showDisableConfirm() + } } + const [isShowDeleteConfirm, { + setTrue: showDeleteConfirm, + setFalse: hideDeleteConfirm, + }] = useBoolean(false) + const handleDelete = async () => { + try { + await deleteEndpoint({ + url: '/workspaces/current/endpoints/delete', + endpointID, + }) + } + catch (error) { + console.error(error) + } + } + + const [isShowEndpointModal, { + setTrue: showEndpointModalConfirm, + setFalse: hideEndpointModalConfirm, + }] = useBoolean(false) + return (
@@ -62,10 +95,10 @@ const EndpointCard = ({
{data.name}
- + - +
@@ -74,7 +107,7 @@ const EndpointCard = ({
{endpoint.method}
-
{`${data.url}${endpoint.path}`}
+
{`${data.url}${endpoint.path}`}
+ {isShowDisableConfirm && ( + {t('plugin.detailPanel.endpointDisableContent', { name: data.name })}
} + onCancel={() => { + hideDisableConfirm() + setActive(true) + }} + onConfirm={inactiveEndpoint} + /> + )} + {isShowDeleteConfirm && ( + {t('plugin.detailPanel.endpointDeleteContent', { name: data.name })}
} + onCancel={hideDeleteConfirm} + onConfirm={handleDelete} + /> + )} + {isShowEndpointModal && ( + + )} ) } diff --git a/web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx b/web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx new file mode 100644 index 0000000000..bc65596044 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx @@ -0,0 +1,79 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { useTranslation } from 'react-i18next' +import Drawer from '@/app/components/base/drawer' +import Button from '@/app/components/base/button' +// import Toast from '@/app/components/base/toast' +// import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form' +// import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general' +import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' +import cn from '@/utils/classnames' + +type Props = { + onCancel: () => void + // onSaved: (value: Record) => void + onRemove?: () => void +} + +const EndpointModal: FC = ({ + onCancel, + // onSaved, + onRemove = () => { }, +}) => { + const { t } = useTranslation() + const language = useLanguage() + + const handleSave = () => { + // for (const field of credentialSchema) { + // if (field.required && !tempCredential[field.name]) { + // Toast.notify({ type: 'error', message: t('common.errorMsg.fieldRequired', { field: field.label[language] || field.label.en_US }) }) + // return + // } + // } + // onSaved(tempCredential) + } + + return ( + + <> + {/*
{ + setTempCredential(v) + }} + formSchemas={credentialSchema} + isEditMode={true} + showOnVariableMap={{}} + validating={false} + inputClassName='!bg-gray-50' + fieldMoreInfo={item => item.url + ? ( + {t('tools.howToGet')} + + ) + : null} + /> */} +
+ < div className='flex space-x-2'> + + +
+ + + + ) +} +export default React.memo(EndpointModal) diff --git a/web/i18n/en-US/plugin.ts b/web/i18n/en-US/plugin.ts index 7decbcd9d4..3866263fb7 100644 --- a/web/i18n/en-US/plugin.ts +++ b/web/i18n/en-US/plugin.ts @@ -21,6 +21,10 @@ const translation = { actionNum: '{{num}} ACTIONS INCLUDED', endpoints: 'Endpoints', endpointsEmpty: 'Click the \'+\' button to add an endpoint', + endpointDisableTip: 'Disable Endpoint', + endpointDisableContent: 'Would you like to disable {{name}}? ', + endpointDeleteTip: 'Remove Endpoint', + endpointDeleteContent: 'Would you like to remove {{name}}? ', serviceOk: 'Service OK', disabled: 'Disabled', modelNum: '{{num}} MODELS INCLUDED', diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts index 118595971f..26f913ce2f 100644 --- a/web/i18n/zh-Hans/plugin.ts +++ b/web/i18n/zh-Hans/plugin.ts @@ -20,7 +20,11 @@ const translation = { }, actionNum: '{{num}} ACTIONS 已包含', endpoints: 'Endpoints', - endpointsEmpty: '点击 \'+\' 按钮添加端点', + endpointsEmpty: '点击 \'+\' 按钮添加 Endpoint', + endpointDisableTip: '停用 Endpoint', + endpointDisableContent: '是否要停用 {{name}} 的 Endpoint ?', + endpointDeleteTip: '移除 Endpoint', + endpointDeleteContent: '是否要移除 {{name}} ?', serviceOk: '服务正常', disabled: '停用', modelNum: '{{num}} 模型已包含',