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 1a984b4eda..14e9abef9b 100644 --- a/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx +++ b/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx @@ -13,11 +13,11 @@ import Indicator from '@/app/components/header/indicator' import Switch from '@/app/components/base/switch' import Toast from '@/app/components/base/toast' import { - deleteEndpoint, - disableEndpoint, - enableEndpoint, - updateEndpoint, -} from '@/service/plugins' + useDeleteEndpoint, + useDisableEndpoint, + useEnableEndpoint, + useUpdateEndpoint, +} from '@/service/use-endpoints' type Props = { data: EndpointListItem @@ -32,43 +32,34 @@ const EndpointCard = ({ const [active, setActive] = useState(data.enabled) const endpointID = data.id + // switch const [isShowDisableConfirm, { setTrue: showDisableConfirm, setFalse: hideDisableConfirm, }] = useBoolean(false) - const activeEndpoint = async () => { - try { - await enableEndpoint({ - url: '/workspaces/current/endpoints/enable', - endpointID, - }) + const { mutate: enableEndpoint } = useEnableEndpoint({ + onSuccess: async () => { await handleChange() - } - catch (error: any) { - console.error(error) + }, + onError: () => { Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) setActive(false) - } - } - const inactiveEndpoint = async () => { - try { - await disableEndpoint({ - url: '/workspaces/current/endpoints/disable', - endpointID, - }) + }, + }) + const { mutate: disableEndpoint } = useDisableEndpoint({ + onSuccess: async () => { await handleChange() hideDisableConfirm() - } - catch (error) { - console.error(error) + }, + onError: () => { Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) - setActive(true) - } - } + setActive(false) + }, + }) const handleSwitch = (state: boolean) => { if (state) { setActive(true) - activeEndpoint() + enableEndpoint(endpointID) } else { setActive(false) @@ -76,30 +67,26 @@ const EndpointCard = ({ } } + // delete const [isShowDeleteConfirm, { setTrue: showDeleteConfirm, setFalse: hideDeleteConfirm, }] = useBoolean(false) - const handleDelete = async () => { - try { - await deleteEndpoint({ - url: '/workspaces/current/endpoints/delete', - endpointID, - }) + const { mutate: deleteEndpoint } = useDeleteEndpoint({ + onSuccess: async () => { await handleChange() hideDeleteConfirm() - } - catch (error) { - console.error(error) + }, + onError: () => { Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) - } - } + }, + }) + // update const [isShowEndpointModal, { setTrue: showEndpointModalConfirm, setFalse: hideEndpointModalConfirm, }] = useBoolean(false) - const formSchemas = useMemo(() => { return toolCredentialToFormSchemas([NAME_FIELD, ...data.declaration.settings]) }, [data.declaration.settings]) @@ -110,27 +97,19 @@ const EndpointCard = ({ } return addDefaultValue(formValue, formSchemas) }, [data.name, data.settings, formSchemas]) - - const handleUpdate = async (state: any) => { - const newName = state.name - delete state.name - try { - await updateEndpoint({ - url: '/workspaces/current/endpoints/update', - body: { - endpoint_id: data.id, - settings: state, - name: newName, - }, - }) + const { mutate: updateEndpoint } = useUpdateEndpoint({ + onSuccess: async () => { await handleChange() hideEndpointModalConfirm() - } - catch (error) { - console.error(error) + }, + onError: () => { Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) - } - } + }, + }) + const handleUpdate = (state: any) => updateEndpoint({ + endpointID, + state, + }) return (
@@ -192,7 +171,7 @@ const EndpointCard = ({ hideDisableConfirm() setActive(true) }} - onConfirm={inactiveEndpoint} + onConfirm={() => disableEndpoint(endpointID)} /> )} {isShowDeleteConfirm && ( @@ -201,7 +180,7 @@ const EndpointCard = ({ title={t('plugin.detailPanel.endpointDeleteTip')} content={
{t('plugin.detailPanel.endpointDeleteContent', { name: data.name })}
} onCancel={hideDeleteConfirm} - onConfirm={handleDelete} + onConfirm={() => deleteEndpoint(endpointID)} /> )} {isShowEndpointModal && ( diff --git a/web/app/components/plugins/plugin-detail-panel/endpoint-list.tsx b/web/app/components/plugins/plugin-detail-panel/endpoint-list.tsx index 6323e42365..b5f5d2768e 100644 --- a/web/app/components/plugins/plugin-detail-panel/endpoint-list.tsx +++ b/web/app/components/plugins/plugin-detail-panel/endpoint-list.tsx @@ -1,6 +1,5 @@ import React, { useMemo } from 'react' import { useTranslation } from 'react-i18next' -import useSWR from 'swr' import { useBoolean } from 'ahooks' import { RiAddLine } from '@remixicon/react' import EndpointModal from './endpoint-modal' @@ -12,9 +11,10 @@ import Tooltip from '@/app/components/base/tooltip' import Toast from '@/app/components/base/toast' import { usePluginPageContext } from '@/app/components/plugins/plugin-page/context' import { - createEndpoint, - fetchEndpointList, -} from '@/service/plugins' + useCreateEndpoint, + useEndpointList, + useInvalidateEndpointList, +} from '@/service/use-endpoints' import cn from '@/utils/classnames' type Props = { @@ -25,17 +25,9 @@ const EndpointList = ({ showTopBorder }: Props) => { const pluginDetail = usePluginPageContext(v => v.currentPluginDetail) const pluginUniqueID = pluginDetail.plugin_unique_identifier const declaration = pluginDetail.declaration.endpoint - const { data, mutate } = useSWR( - { - url: '/workspaces/current/endpoints/list/plugin', - params: { - plugin_id: pluginDetail.plugin_id, - page: 1, - page_size: 100, - }, - }, - fetchEndpointList, - ) + const { data } = useEndpointList(pluginDetail.plugin_id) + const invalidateEndpointList = useInvalidateEndpointList() + const [isShowEndpointModal, { setTrue: showEndpointModal, setFalse: hideEndpointModal, @@ -45,26 +37,20 @@ const EndpointList = ({ showTopBorder }: Props) => { return toolCredentialToFormSchemas([NAME_FIELD, ...declaration.settings]) }, [declaration.settings]) - const handleCreate = async (state: any) => { - const newName = state.name - delete state.name - try { - await createEndpoint({ - url: '/workspaces/current/endpoints/create', - body: { - plugin_unique_identifier: pluginUniqueID, - settings: state, - name: newName, - }, - }) - await mutate() + const { mutate: createEndpoint } = useCreateEndpoint({ + onSuccess: async () => { + await invalidateEndpointList(pluginDetail.plugin_id) hideEndpointModal() - } - catch (error) { - console.error(error) + }, + onError: () => { Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) - } - } + }, + }) + + const handleCreate = (state: any) => createEndpoint({ + pluginUniqueID, + state, + }) if (!data) return null @@ -92,7 +78,7 @@ const EndpointList = ({ showTopBorder }: Props) => { invalidateEndpointList(pluginDetail.plugin_id)} /> ))}
diff --git a/web/app/components/plugins/types.ts b/web/app/components/plugins/types.ts index 629b9b7582..40627f67a3 100644 --- a/web/app/components/plugins/types.ts +++ b/web/app/components/plugins/types.ts @@ -194,19 +194,10 @@ export type GitHubUrlInfo = { } // endpoint -export type CreateEndpointRequest = { - plugin_unique_identifier: string - settings: Record - name: string -} export type EndpointOperationResponse = { result: 'success' | 'error' } -export type EndpointsRequest = { - page_size: number - page: number - plugin_id: string -} + export type EndpointsResponse = { endpoints: EndpointListItem[] has_more: boolean diff --git a/web/service/plugins.ts b/web/service/plugins.ts index 3e5d872bf2..999ed4f1b9 100644 --- a/web/service/plugins.ts +++ b/web/service/plugins.ts @@ -1,10 +1,6 @@ import type { Fetcher } from 'swr' import { get, getMarketplace, post, upload } from './base' import type { - CreateEndpointRequest, - EndpointOperationResponse, - EndpointsRequest, - EndpointsResponse, InstallPackageResponse, Permissions, PluginDeclaration, @@ -12,7 +8,6 @@ import type { PluginTasksResponse, TaskStatusResponse, UninstallPluginResponse, - UpdateEndpointRequest, uploadGitHubResponse, } from '@/app/components/plugins/types' import type { @@ -20,36 +15,6 @@ import type { MarketplaceCollectionsResponse, } from '@/app/components/plugins/marketplace/types' -export const createEndpoint: Fetcher = ({ url, body }) => { - // url = /workspaces/current/endpoints/create - return post(url, { body }) -} - -export const fetchEndpointList: Fetcher = ({ url, params }) => { - // url = /workspaces/current/endpoints/list/plugin?plugin_id=xxx - return get(url, { params }) -} - -export const deleteEndpoint: Fetcher = ({ url, endpointID }) => { - // url = /workspaces/current/endpoints/delete - return post(url, { body: { endpoint_id: endpointID } }) -} - -export const updateEndpoint: Fetcher = ({ url, body }) => { - // url = /workspaces/current/endpoints/update - return post(url, { body }) -} - -export const enableEndpoint: Fetcher = ({ url, endpointID }) => { - // url = /workspaces/current/endpoints/enable - return post(url, { body: { endpoint_id: endpointID } }) -} - -export const disableEndpoint: Fetcher = ({ url, endpointID }) => { - // url = /workspaces/current/endpoints/disable - return post(url, { body: { endpoint_id: endpointID } }) -} - export const uploadPackageFile = async (file: File) => { const formData = new FormData() formData.append('pkg', file) diff --git a/web/service/use-endpoints.ts b/web/service/use-endpoints.ts new file mode 100644 index 0000000000..43a82480b9 --- /dev/null +++ b/web/service/use-endpoints.ts @@ -0,0 +1,149 @@ +import { get, post } from './base' +import type { + EndpointsResponse, +} from '@/app/components/plugins/types' +import { + useMutation, + useQuery, + useQueryClient, +} from '@tanstack/react-query' + +const NAME_SPACE = 'endpoints' + +export const useEndpointList = (pluginID: string) => { + return useQuery({ + queryKey: [NAME_SPACE, 'list', pluginID], + queryFn: () => get('/workspaces/current/endpoints/list/plugin', { + params: { + plugin_id: pluginID, + page: 1, + page_size: 100, + }, + }), + }) +} + +export const useInvalidateEndpointList = () => { + const queryClient = useQueryClient() + return (pluginID: string) => { + queryClient.invalidateQueries( + { + queryKey: [NAME_SPACE, 'list', pluginID], + }) + } +} + +export const useCreateEndpoint = ({ + onSuccess, + onError, +}: { + onSuccess?: () => void + onError?: (error: any) => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'create'], + mutationFn: (payload: { pluginUniqueID: string, state: Record }) => { + const { pluginUniqueID, state } = payload + const newName = state.name + delete state.name + return post('/workspaces/current/endpoints/create', { + body: { + plugin_unique_identifier: pluginUniqueID, + settings: state, + name: newName, + }, + }) + }, + onSuccess, + onError, + }) +} + +export const useUpdateEndpoint = ({ + onSuccess, + onError, +}: { + onSuccess?: () => void + onError?: (error: any) => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'update'], + mutationFn: (payload: { endpointID: string, state: Record }) => { + const { endpointID, state } = payload + const newName = state.name + delete state.name + return post('/workspaces/current/endpoints/update', { + body: { + endpoint_id: endpointID, + settings: state, + name: newName, + }, + }) + }, + onSuccess, + onError, + }) +} + +export const useDeleteEndpoint = ({ + onSuccess, + onError, +}: { + onSuccess?: () => void + onError?: (error: any) => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'delete'], + mutationFn: (endpointID: string) => { + return post('/workspaces/current/endpoints/delete', { + body: { + endpoint_id: endpointID, + }, + }) + }, + onSuccess, + onError, + }) +} + +export const useEnableEndpoint = ({ + onSuccess, + onError, +}: { + onSuccess?: () => void + onError?: (error: any) => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'enable'], + mutationFn: (endpointID: string) => { + return post('/workspaces/current/endpoints/enable', { + body: { + endpoint_id: endpointID, + }, + }) + }, + onSuccess, + onError, + }) +} + +export const useDisableEndpoint = ({ + onSuccess, + onError, +}: { + onSuccess?: () => void + onError?: (error: any) => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'disable'], + mutationFn: (endpointID: string) => { + return post('/workspaces/current/endpoints/disable', { + body: { + endpoint_id: endpointID, + }, + }) + }, + onSuccess, + onError, + }) +} diff --git a/web/service/use-tools.ts b/web/service/use-tools.ts index 0d0f816b3e..3c34de3be9 100644 --- a/web/service/use-tools.ts +++ b/web/service/use-tools.ts @@ -74,6 +74,7 @@ export const useUpdateProviderCredentials = ({ onSuccess?: () => void }) => { return useMutation({ + mutationKey: [NAME_SPACE, 'update-provider-credentials'], mutationFn: (payload: { providerName: string, credentials: Record }) => { const { providerName, credentials } = payload return post(`/workspaces/current/tool-provider/builtin/${providerName}/update`, { @@ -92,6 +93,7 @@ export const useRemoveProviderCredentials = ({ onSuccess?: () => void }) => { return useMutation({ + mutationKey: [NAME_SPACE, 'remove-provider-credentials'], mutationFn: (providerName: string) => { return post(`/workspaces/current/tool-provider/builtin/${providerName}/delete`, { body: {},