diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index e6fab131196..aa6b95541ae 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -5974,16 +5974,6 @@ "count": 1 } }, - "web/context/external-api-panel-context.tsx": { - "react/only-export-components": { - "count": 1 - } - }, - "web/context/external-knowledge-api-context.tsx": { - "react/only-export-components": { - "count": 1 - } - }, "web/context/hooks/use-trigger-events-limit-modal.ts": { "eslint-react/set-state-in-effect": { "count": 3 diff --git a/web/app/(commonLayout)/datasets/layout.spec.tsx b/web/app/(commonLayout)/datasets/layout.spec.tsx index 2dd57fedee2..a99a99f7fe8 100644 --- a/web/app/(commonLayout)/datasets/layout.spec.tsx +++ b/web/app/(commonLayout)/datasets/layout.spec.tsx @@ -1,4 +1,3 @@ -import type { ReactNode } from 'react' import { screen, waitFor } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' import { render } from '@/test/console/render' @@ -7,7 +6,6 @@ import DatasetsLayout from './layout' const mockReplace = vi.fn() const mockConsoleStateReader = vi.fn() let mockPathname = '/datasets' -let mockExternalKnowledgeApiProviderEnabled: boolean | undefined vi.mock('@/next/navigation', () => ({ useRouter: () => ({ @@ -27,23 +25,6 @@ vi.mock('@/context/permission-state', async () => { return createPermissionStateModuleMock(() => mockConsoleStateReader()) }) -vi.mock('@/context/external-api-panel-context', () => ({ - ExternalApiPanelProvider: ({ children }: { children: ReactNode }) => <>{children}, -})) - -vi.mock('@/context/external-knowledge-api-context', () => ({ - ExternalKnowledgeApiProvider: ({ - children, - enabled, - }: { - children: ReactNode - enabled?: boolean - }) => { - mockExternalKnowledgeApiProviderEnabled = enabled - return <>{children} - }, -})) - type ConsoleStateFixture = { isCurrentWorkspaceEditor: boolean isCurrentWorkspaceDatasetOperator: boolean @@ -77,7 +58,6 @@ describe('DatasetsLayout', () => { beforeEach(() => { vi.clearAllMocks() mockPathname = '/datasets' - mockExternalKnowledgeApiProviderEnabled = undefined setConsoleState() }) @@ -241,32 +221,4 @@ describe('DatasetsLayout', () => { expect(mockReplace).not.toHaveBeenCalled() }, ) - - it('should disable external knowledge API queries without dataset.external.connect', () => { - setConsoleState({ - workspacePermissionKeys: [], - }) - - render( - -
datasets
-
, - ) - - expect(mockExternalKnowledgeApiProviderEnabled).toBe(false) - }) - - it('should enable external knowledge API queries with dataset.external.connect', () => { - setConsoleState({ - workspacePermissionKeys: ['dataset.external.connect'], - }) - - render( - -
datasets
-
, - ) - - expect(mockExternalKnowledgeApiProviderEnabled).toBe(true) - }) }) diff --git a/web/app/(commonLayout)/datasets/layout.tsx b/web/app/(commonLayout)/datasets/layout.tsx index 2ec5becd38b..4cd87ffb8bb 100644 --- a/web/app/(commonLayout)/datasets/layout.tsx +++ b/web/app/(commonLayout)/datasets/layout.tsx @@ -3,8 +3,6 @@ import { useAtomValue } from 'jotai' import { useEffect } from 'react' import Loading from '@/app/components/base/loading' -import { ExternalApiPanelProvider } from '@/context/external-api-panel-context' -import { ExternalKnowledgeApiProvider } from '@/context/external-knowledge-api-context' import { workspacePermissionKeysAtom, workspacePermissionKeysLoadingAtom, @@ -60,9 +58,5 @@ export default function DatasetsLayout({ children }: { children: React.ReactNode return null } - return ( - - {children} - - ) + return children } diff --git a/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx b/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx index fcf30d03f0b..e9bbbf1a503 100644 --- a/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx +++ b/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx @@ -1,4 +1,4 @@ -import type { ExternalAPIItem } from '@/models/datasets' +import type { ExternalKnowledgeApiResponse } from '@dify/contracts/api/console/datasets/types.gen' import { fireEvent, render, screen, waitFor } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' import ExternalAPIPanel from '../index' @@ -7,11 +7,11 @@ vi.mock('@/context/i18n', () => ({ useDocLink: () => (path: string) => `https://docs.example.com${path}`, })) -// Mock external contexts (only mock context providers, not base components) const mockSetShowExternalKnowledgeAPIModal = vi.fn() -const mockMutateExternalKnowledgeApis = vi.fn() +const mockInvalidateQueries = vi.fn() +const externalKnowledgeApiQueryKey = ['console', 'datasets', 'externalKnowledgeApi', 'get'] let mockIsLoading = false -let mockExternalKnowledgeApiList: ExternalAPIItem[] = [] +let mockExternalKnowledgeApiList: ExternalKnowledgeApiResponse[] = [] vi.mock('@/context/modal-context', () => ({ useModalContext: () => ({ @@ -19,12 +19,30 @@ vi.mock('@/context/modal-context', () => ({ }), })) -vi.mock('@/context/external-knowledge-api-context', () => ({ - useExternalKnowledgeApi: () => ({ - externalKnowledgeApiList: mockExternalKnowledgeApiList, - mutateExternalKnowledgeApis: mockMutateExternalKnowledgeApis, - isLoading: mockIsLoading, - }), +vi.mock('@tanstack/react-query', async (importOriginal) => { + const original = await importOriginal() + return { + ...original, + useQuery: () => ({ + data: { data: mockExternalKnowledgeApiList }, + isLoading: mockIsLoading, + }), + useQueryClient: () => ({ invalidateQueries: mockInvalidateQueries }), + } +}) + +vi.mock('@/service/client', () => ({ + consoleQuery: { + datasets: { + externalKnowledgeApi: { + get: { + queryOptions: () => ({ + queryKey: ['console', 'datasets', 'externalKnowledgeApi', 'get'], + }), + }, + }, + }, + }, })) // Mock the ExternalKnowledgeAPICard to avoid mocking its internal dependencies @@ -33,7 +51,7 @@ vi.mock('../../external-knowledge-api-card', () => ({ api, canManageExternalKnowledgeApi, }: { - api: ExternalAPIItem + api: ExternalKnowledgeApiResponse canManageExternalKnowledgeApi: boolean }) => (
{ }) }) - it('should call mutateExternalKnowledgeApis in onSaveCallback', async () => { + it('should invalidate the generated external API query after creation', async () => { render() const createButton = screen.getByText('dataset.createExternalAPI').closest('button')! fireEvent.click(createButton) const callArgs = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] - callArgs.onSaveCallback() + await callArgs.onSaveCallback() - expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() + expect(mockInvalidateQueries).toHaveBeenCalledWith({ + queryKey: externalKnowledgeApiQueryKey, + }) }) - it('should call mutateExternalKnowledgeApis in onCancelCallback', async () => { + it('should not refresh the query when creation is canceled', async () => { render() const createButton = screen.getByText('dataset.createExternalAPI').closest('button')! fireEvent.click(createButton) const callArgs = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] - callArgs.onCancelCallback() - expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() + expect(callArgs.onCancelCallback).toBeUndefined() + expect(mockInvalidateQueries).not.toHaveBeenCalled() }) }) diff --git a/web/app/components/datasets/external-api/external-api-panel/index.tsx b/web/app/components/datasets/external-api/external-api-panel/index.tsx index a5eca0b4c90..fee862d8488 100644 --- a/web/app/components/datasets/external-api/external-api-panel/index.tsx +++ b/web/app/components/datasets/external-api/external-api-panel/index.tsx @@ -1,13 +1,14 @@ import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' import { RiAddLine, RiBookOpenLine, RiCloseLine } from '@remixicon/react' +import { useQuery, useQueryClient } from '@tanstack/react-query' import * as React from 'react' import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' import Loading from '@/app/components/base/loading' -import { useExternalKnowledgeApi } from '@/context/external-knowledge-api-context' import { useDocLink } from '@/context/i18n' import { useModalContext } from '@/context/modal-context' +import { consoleQuery } from '@/service/client' import ExternalKnowledgeAPICard from '../external-knowledge-api-card' type ExternalAPIPanelProps = { @@ -22,8 +23,11 @@ const ExternalAPIPanel: React.FC = ({ const { t } = useTranslation() const docLink = useDocLink() const { setShowExternalKnowledgeAPIModal } = useModalContext() - const { externalKnowledgeApiList, mutateExternalKnowledgeApis, isLoading } = - useExternalKnowledgeApi() + const queryClient = useQueryClient() + const externalKnowledgeApiQueryOptions = + consoleQuery.datasets.externalKnowledgeApi.get.queryOptions({ input: {} }) + const { data, isLoading } = useQuery(externalKnowledgeApiQueryOptions) + const externalKnowledgeApiList = data?.data ?? [] const handleOpenExternalAPIModal = () => { if (!canManageExternalKnowledgeApi) return @@ -32,10 +36,9 @@ const ExternalAPIPanel: React.FC = ({ payload: { name: '', settings: { endpoint: '', api_key: '' } }, datasetBindings: [], onSaveCallback: () => { - mutateExternalKnowledgeApis() - }, - onCancelCallback: () => { - mutateExternalKnowledgeApis() + void queryClient.invalidateQueries({ + queryKey: externalKnowledgeApiQueryOptions.queryKey, + }) }, isEditMode: false, }) diff --git a/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx b/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx index e441016cf5e..5a3bc766f24 100644 --- a/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx +++ b/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx @@ -1,8 +1,14 @@ +import type { ExternalKnowledgeApiResponse } from '@dify/contracts/api/console/datasets/types.gen' import type { ExternalAPIItem } from '@/models/datasets' import { fireEvent, render, screen, waitFor } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' // Import mocked services -import { checkUsageExternalAPI, deleteExternalAPI, fetchExternalAPI } from '@/service/datasets' +import { + checkUsageExternalAPI, + deleteExternalAPI, + fetchExternalAPI, + updateExternalAPI, +} from '@/service/datasets' import ExternalKnowledgeAPICard from '../index' // Mock API services @@ -15,7 +21,8 @@ vi.mock('@/service/datasets', () => ({ // Mock contexts const mockSetShowExternalKnowledgeAPIModal = vi.fn() -const mockMutateExternalKnowledgeApis = vi.fn() +const mockInvalidateQueries = vi.fn() +const externalKnowledgeApiQueryKey = ['console', 'datasets', 'externalKnowledgeApi', 'get'] vi.mock('@/context/modal-context', () => ({ useModalContext: () => ({ @@ -23,14 +30,30 @@ vi.mock('@/context/modal-context', () => ({ }), })) -vi.mock('@/context/external-knowledge-api-context', () => ({ - useExternalKnowledgeApi: () => ({ - mutateExternalKnowledgeApis: mockMutateExternalKnowledgeApis, - }), +vi.mock('@tanstack/react-query', async (importOriginal) => { + const original = await importOriginal() + return { + ...original, + useQueryClient: () => ({ invalidateQueries: mockInvalidateQueries }), + } +}) + +vi.mock('@/service/client', () => ({ + consoleQuery: { + datasets: { + externalKnowledgeApi: { + get: { + queryOptions: () => ({ + queryKey: ['console', 'datasets', 'externalKnowledgeApi', 'get'], + }), + }, + }, + }, + }, })) describe('ExternalKnowledgeAPICard', () => { - const mockApi: ExternalAPIItem = { + const mockApi: ExternalKnowledgeApiResponse = { id: 'api-123', tenant_id: 'tenant-1', name: 'Test External API', @@ -146,7 +169,7 @@ describe('ExternalKnowledgeAPICard', () => { consoleSpy.mockRestore() }) - it('should call mutate on save callback', async () => { + it('should invalidate the generated list query after editing', async () => { const mockResponse: ExternalAPIItem = { id: 'api-123', tenant_id: 'tenant-1', @@ -171,14 +194,31 @@ describe('ExternalKnowledgeAPICard', () => { expect(mockSetShowExternalKnowledgeAPIModal).toHaveBeenCalled() }) - // Simulate save callback const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] - modalCall.onSaveCallback() + await modalCall.onEditCallback({ + name: 'Updated External API', + settings: { + endpoint: 'https://updated.example.com/knowledge', + api_key: 'updated-secret-key', + }, + }) - expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() + expect(updateExternalAPI).toHaveBeenCalledWith({ + apiTemplateId: 'api-123', + body: expect.objectContaining({ + name: 'Updated External API', + settings: { + endpoint: 'https://updated.example.com/knowledge', + api_key: 'updated-secret-key', + }, + }), + }) + expect(mockInvalidateQueries).toHaveBeenCalledWith({ + queryKey: externalKnowledgeApiQueryKey, + }) }) - it('should call mutate on cancel callback', async () => { + it('should not refresh the list query when editing is canceled', async () => { const mockResponse: ExternalAPIItem = { id: 'api-123', tenant_id: 'tenant-1', @@ -203,11 +243,10 @@ describe('ExternalKnowledgeAPICard', () => { expect(mockSetShowExternalKnowledgeAPIModal).toHaveBeenCalled() }) - // Simulate cancel callback const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] - modalCall.onCancelCallback() - expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() + expect(modalCall.onCancelCallback).toBeUndefined() + expect(mockInvalidateQueries).not.toHaveBeenCalled() }) }) @@ -262,7 +301,9 @@ describe('ExternalKnowledgeAPICard', () => { await waitFor(() => { expect(deleteExternalAPI).toHaveBeenCalledWith({ apiTemplateId: 'api-123' }) - expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() + expect(mockInvalidateQueries).toHaveBeenCalledWith({ + queryKey: externalKnowledgeApiQueryKey, + }) }) }) @@ -335,7 +376,7 @@ describe('ExternalKnowledgeAPICard', () => { describe('Edge Cases', () => { it('should handle API with empty endpoint', () => { - const apiWithEmptyEndpoint: ExternalAPIItem = { + const apiWithEmptyEndpoint: ExternalKnowledgeApiResponse = { ...mockApi, settings: { endpoint: '', api_key: 'key' }, } diff --git a/web/app/components/datasets/external-api/external-knowledge-api-card/index.tsx b/web/app/components/datasets/external-api/external-knowledge-api-card/index.tsx index 71fd8b7a910..54b100e9361 100644 --- a/web/app/components/datasets/external-api/external-knowledge-api-card/index.tsx +++ b/web/app/components/datasets/external-api/external-knowledge-api-card/index.tsx @@ -1,5 +1,5 @@ +import type { ExternalKnowledgeApiResponse } from '@dify/contracts/api/console/datasets/types.gen' import type { CreateExternalAPIReq } from '../declarations' -import type { ExternalAPIItem } from '@/models/datasets' import { AlertDialog, AlertDialogActions, @@ -10,13 +10,14 @@ import { AlertDialogTitle, } from '@langgenius/dify-ui/alert-dialog' import { RiDeleteBinLine, RiEditLine } from '@remixicon/react' +import { useQueryClient } from '@tanstack/react-query' import * as React from 'react' import { useState } from 'react' import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development' -import { useExternalKnowledgeApi } from '@/context/external-knowledge-api-context' import { useModalContext } from '@/context/modal-context' +import { consoleQuery } from '@/service/client' import { checkUsageExternalAPI, deleteExternalAPI, @@ -25,7 +26,7 @@ import { } from '@/service/datasets' type ExternalKnowledgeAPICardProps = { - api: ExternalAPIItem + api: ExternalKnowledgeApiResponse canManageExternalKnowledgeApi: boolean } @@ -37,7 +38,12 @@ const ExternalKnowledgeAPICard: React.FC = ({ const [showConfirm, setShowConfirm] = useState(false) const [isHovered, setIsHovered] = useState(false) const [usageCount, setUsageCount] = useState(0) - const { mutateExternalKnowledgeApis } = useExternalKnowledgeApi() + const queryClient = useQueryClient() + const externalKnowledgeApiQueryKey = consoleQuery.datasets.externalKnowledgeApi.get.queryOptions({ + input: {}, + }).queryKey + const endpoint = + api.settings && typeof api.settings.endpoint === 'string' ? api.settings.endpoint : '' const { t } = useTranslation() @@ -56,12 +62,6 @@ const ExternalKnowledgeAPICard: React.FC = ({ setShowExternalKnowledgeAPIModal({ payload: formValue, - onSaveCallback: () => { - mutateExternalKnowledgeApis() - }, - onCancelCallback: () => { - mutateExternalKnowledgeApis() - }, isEditMode: true, datasetBindings: response.dataset_bindings, onEditCallback: async (updatedData: CreateExternalAPIReq) => { @@ -78,7 +78,7 @@ const ExternalKnowledgeAPICard: React.FC = ({ }, }, }) - mutateExternalKnowledgeApis() + await queryClient.invalidateQueries({ queryKey: externalKnowledgeApiQueryKey }) } catch (error) { console.error('Error updating external knowledge API:', error) } @@ -109,7 +109,7 @@ const ExternalKnowledgeAPICard: React.FC = ({ const response = await deleteExternalAPI({ apiTemplateId: api.id }) if (response && response.result === 'success') { setShowConfirm(false) - mutateExternalKnowledgeApis() + await queryClient.invalidateQueries({ queryKey: externalKnowledgeApiQueryKey }) } else { console.error('Failed to delete external API') } @@ -128,9 +128,7 @@ const ExternalKnowledgeAPICard: React.FC = ({
{api.name}
-
- {api.settings.endpoint} -
+
{endpoint}
{canManageExternalKnowledgeApi && (
diff --git a/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx b/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx index fca2f5aca38..0dd4d7d57bb 100644 --- a/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx +++ b/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx @@ -79,12 +79,27 @@ const createDefaultMockApiList = (): ExternalAPIItem[] => [ let mockExternalKnowledgeApiList: ExternalAPIItem[] = createDefaultMockApiList() -vi.mock('@/context/external-knowledge-api-context', () => ({ - useExternalKnowledgeApi: () => ({ - externalKnowledgeApiList: mockExternalKnowledgeApiList, - mutateExternalKnowledgeApis: vi.fn(), - isLoading: false, - }), +vi.mock('@tanstack/react-query', async (importOriginal) => { + const original = await importOriginal() + return { + ...original, + useQuery: () => ({ data: { data: mockExternalKnowledgeApiList } }), + useQueryClient: () => ({ invalidateQueries: vi.fn() }), + } +}) + +vi.mock('@/service/client', () => ({ + consoleQuery: { + datasets: { + externalKnowledgeApi: { + get: { + queryOptions: () => ({ + queryKey: ['console', 'datasets', 'externalKnowledgeApi', 'get'], + }), + }, + }, + }, + }, })) // Suppress console.error helper diff --git a/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelect.tsx b/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelect.tsx index 2dc8ca62b4b..1bd52132e57 100644 --- a/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelect.tsx +++ b/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelect.tsx @@ -1,11 +1,12 @@ import { RiAddLine, RiArrowDownSLine } from '@remixicon/react' +import { useQueryClient } from '@tanstack/react-query' import * as React from 'react' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development' -import { useExternalKnowledgeApi } from '@/context/external-knowledge-api-context' import { useModalContext } from '@/context/modal-context' import { useRouter } from '@/next/navigation' +import { consoleQuery } from '@/service/client' type ApiItem = { value: string @@ -26,7 +27,10 @@ const ExternalApiSelect: React.FC = ({ items, value, onS items.find((item) => item.value === value) || null, ) const { setShowExternalKnowledgeAPIModal } = useModalContext() - const { mutateExternalKnowledgeApis } = useExternalKnowledgeApi() + const queryClient = useQueryClient() + const externalKnowledgeApiQueryKey = consoleQuery.datasets.externalKnowledgeApi.get.queryOptions({ + input: {}, + }).queryKey const router = useRouter() useEffect(() => { @@ -38,12 +42,9 @@ const ExternalApiSelect: React.FC = ({ items, value, onS setShowExternalKnowledgeAPIModal({ payload: { name: '', settings: { endpoint: '', api_key: '' } }, onSaveCallback: async () => { - mutateExternalKnowledgeApis() + await queryClient.invalidateQueries({ queryKey: externalKnowledgeApiQueryKey }) router.refresh() }, - onCancelCallback: () => { - mutateExternalKnowledgeApis() - }, isEditMode: false, }) } diff --git a/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx b/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx index 6cee272f841..e5d1ba46d6e 100644 --- a/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx +++ b/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx @@ -2,13 +2,14 @@ import { Button } from '@langgenius/dify-ui/button' import { RiAddLine } from '@remixicon/react' +import { useQuery, useQueryClient } from '@tanstack/react-query' import * as React from 'react' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import Input from '@/app/components/base/input' -import { useExternalKnowledgeApi } from '@/context/external-knowledge-api-context' import { useModalContext } from '@/context/modal-context' import { useRouter } from '@/next/navigation' +import { consoleQuery } from '@/service/client' import ExternalApiSelect from './ExternalApiSelect' type ExternalApiSelectionProps = { @@ -24,15 +25,18 @@ const ExternalApiSelection: React.FC = ({ }) => { const { t } = useTranslation() const router = useRouter() - const { externalKnowledgeApiList } = useExternalKnowledgeApi() + const queryClient = useQueryClient() + const externalKnowledgeApiQueryOptions = + consoleQuery.datasets.externalKnowledgeApi.get.queryOptions({ input: {} }) + const { data } = useQuery(externalKnowledgeApiQueryOptions) + const externalKnowledgeApiList = data?.data ?? [] const [selectedApiId, setSelectedApiId] = useState(external_knowledge_api_id) const { setShowExternalKnowledgeAPIModal } = useModalContext() - const { mutateExternalKnowledgeApis } = useExternalKnowledgeApi() const apiItems = externalKnowledgeApiList.map((api) => ({ value: api.id, name: api.name, - url: api.settings.endpoint, + url: api.settings && typeof api.settings.endpoint === 'string' ? api.settings.endpoint : '', })) useEffect(() => { @@ -48,12 +52,11 @@ const ExternalApiSelection: React.FC = ({ setShowExternalKnowledgeAPIModal({ payload: { name: '', settings: { endpoint: '', api_key: '' } }, onSaveCallback: async () => { - mutateExternalKnowledgeApis() + await queryClient.invalidateQueries({ + queryKey: externalKnowledgeApiQueryOptions.queryKey, + }) router.refresh() }, - onCancelCallback: () => { - mutateExternalKnowledgeApis() - }, isEditMode: false, }) } diff --git a/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelect.spec.tsx b/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelect.spec.tsx index 7af75fbcdd2..5dfa11f5b79 100644 --- a/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelect.spec.tsx +++ b/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelect.spec.tsx @@ -9,7 +9,7 @@ const mocks = vi.hoisted(() => ({ push: vi.fn(), refresh: vi.fn(), setShowExternalKnowledgeAPIModal: vi.fn(), - mutateExternalKnowledgeApis: vi.fn(), + invalidateQueries: vi.fn(), })) vi.mock('@/next/navigation', () => ({ @@ -22,10 +22,28 @@ vi.mock('@/context/modal-context', () => ({ }), })) -vi.mock('@/context/external-knowledge-api-context', () => ({ - useExternalKnowledgeApi: () => ({ - mutateExternalKnowledgeApis: mocks.mutateExternalKnowledgeApis, - }), +const externalKnowledgeApiQueryKey = ['console', 'datasets', 'externalKnowledgeApi', 'get'] + +vi.mock('@tanstack/react-query', async (importOriginal) => { + const original = await importOriginal() + return { + ...original, + useQueryClient: () => ({ invalidateQueries: mocks.invalidateQueries }), + } +}) + +vi.mock('@/service/client', () => ({ + consoleQuery: { + datasets: { + externalKnowledgeApi: { + get: { + queryOptions: () => ({ + queryKey: ['console', 'datasets', 'externalKnowledgeApi', 'get'], + }), + }, + }, + }, + }, })) vi.mock('@/app/components/base/icons/src/vender/solid/development', () => ({ @@ -87,11 +105,19 @@ describe('ExternalApiSelect', () => { expect(screen.getByText('dataset.createNewExternalAPI')).toBeInTheDocument() }) - it('should call setShowExternalKnowledgeAPIModal when add new clicked', () => { + it('should invalidate the generated query after creating an external API', async () => { render() fireEvent.click(screen.getByText('dataset.selectExternalKnowledgeAPI.placeholder')) fireEvent.click(screen.getByText('dataset.createNewExternalAPI')) expect(mocks.setShowExternalKnowledgeAPIModal).toHaveBeenCalledOnce() + + const modalConfig = mocks.setShowExternalKnowledgeAPIModal.mock.calls[0]![0] + await modalConfig.onSaveCallback() + + expect(mocks.invalidateQueries).toHaveBeenCalledWith({ + queryKey: externalKnowledgeApiQueryKey, + }) + expect(mocks.refresh).toHaveBeenCalledOnce() }) it('should show item URLs in dropdown', () => { diff --git a/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelection.spec.tsx b/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelection.spec.tsx index cfd79fe8bc9..5b3240501dd 100644 --- a/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelection.spec.tsx +++ b/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelection.spec.tsx @@ -6,6 +6,7 @@ const mocks = vi.hoisted(() => ({ push: vi.fn(), refresh: vi.fn(), setShowExternalKnowledgeAPIModal: vi.fn(), + invalidateQueries: vi.fn(), externalKnowledgeApiList: [] as Array<{ id: string name: string @@ -23,10 +24,29 @@ vi.mock('@/context/modal-context', () => ({ }), })) -vi.mock('@/context/external-knowledge-api-context', () => ({ - useExternalKnowledgeApi: () => ({ - externalKnowledgeApiList: mocks.externalKnowledgeApiList, - }), +const externalKnowledgeApiQueryKey = ['console', 'datasets', 'externalKnowledgeApi', 'get'] + +vi.mock('@tanstack/react-query', async (importOriginal) => { + const original = await importOriginal() + return { + ...original, + useQuery: () => ({ data: { data: mocks.externalKnowledgeApiList } }), + useQueryClient: () => ({ invalidateQueries: mocks.invalidateQueries }), + } +}) + +vi.mock('@/service/client', () => ({ + consoleQuery: { + datasets: { + externalKnowledgeApi: { + get: { + queryOptions: () => ({ + queryKey: ['console', 'datasets', 'externalKnowledgeApi', 'get'], + }), + }, + }, + }, + }, })) vi.mock('../ExternalApiSelect', () => ({ @@ -108,4 +128,19 @@ describe('ExternalApiSelection', () => { expect(mocks.setShowExternalKnowledgeAPIModal).toHaveBeenCalledOnce() }) + + it('invalidates the generated query after creating an external API', async () => { + const user = userEvent.setup() + mocks.externalKnowledgeApiList = [] + render() + + await user.click(screen.getByRole('button', { name: 'dataset.noExternalKnowledge' })) + const modalConfig = mocks.setShowExternalKnowledgeAPIModal.mock.calls[0]![0] + await modalConfig.onSaveCallback() + + expect(mocks.invalidateQueries).toHaveBeenCalledWith({ + queryKey: externalKnowledgeApiQueryKey, + }) + expect(mocks.refresh).toHaveBeenCalledOnce() + }) }) diff --git a/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx b/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx index 0a1237b6fc0..521d9d3dcd5 100644 --- a/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx +++ b/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx @@ -21,7 +21,7 @@ vi.mock('@/context/i18n', () => ({ `https://docs.dify.ai/en${path?.startsWith('/use-dify/') ? `/cloud${path}` : path || ''}`, })) -// Mock external context providers (these are external dependencies) +// Mock the shared modal owner. const mockSetShowExternalKnowledgeAPIModal = vi.fn() vi.mock('@/context/modal-context', () => ({ useModalContext: () => ({ @@ -59,15 +59,31 @@ const createDefaultMockApiList = (): ExternalAPIItem[] => [ }), ] -const mockMutateExternalKnowledgeApis = vi.fn() +const mockInvalidateQueries = vi.fn() +const externalKnowledgeApiQueryKey = ['console', 'datasets', 'externalKnowledgeApi', 'get'] let mockExternalKnowledgeApiList: ExternalAPIItem[] = createDefaultMockApiList() -vi.mock('@/context/external-knowledge-api-context', () => ({ - useExternalKnowledgeApi: () => ({ - externalKnowledgeApiList: mockExternalKnowledgeApiList, - mutateExternalKnowledgeApis: mockMutateExternalKnowledgeApis, - isLoading: false, - }), +vi.mock('@tanstack/react-query', async (importOriginal) => { + const original = await importOriginal() + return { + ...original, + useQuery: () => ({ data: { data: mockExternalKnowledgeApiList } }), + useQueryClient: () => ({ invalidateQueries: mockInvalidateQueries }), + } +}) + +vi.mock('@/service/client', () => ({ + consoleQuery: { + datasets: { + externalKnowledgeApi: { + get: { + queryOptions: () => ({ + queryKey: ['console', 'datasets', 'externalKnowledgeApi', 'get'], + }), + }, + }, + }, + }, })) // Helper to render component with default props @@ -523,7 +539,7 @@ describe('ExternalKnowledgeBaseCreate', () => { ) }) - it('should call mutate and router.refresh on modal save callback', async () => { + it('should invalidate the generated query and refresh after modal save', async () => { const user = userEvent.setup() // Set empty API list mockExternalKnowledgeApiList = [] @@ -536,11 +552,13 @@ describe('ExternalKnowledgeBaseCreate', () => { const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] await modalCall.onSaveCallback() - expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() + expect(mockInvalidateQueries).toHaveBeenCalledWith({ + queryKey: externalKnowledgeApiQueryKey, + }) expect(mockRefresh).toHaveBeenCalled() }) - it('should call mutate on modal cancel callback', async () => { + it('should not invalidate the generated query when the modal is canceled', async () => { const user = userEvent.setup() // Set empty API list mockExternalKnowledgeApiList = [] @@ -551,9 +569,8 @@ describe('ExternalKnowledgeBaseCreate', () => { // Get the callback and invoke it const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] - modalCall.onCancelCallback() - - expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() + expect(modalCall.onCancelCallback).toBeUndefined() + expect(mockInvalidateQueries).not.toHaveBeenCalled() }) it('should display API URL in dropdown', async () => { @@ -600,7 +617,7 @@ describe('ExternalKnowledgeBaseCreate', () => { ) }) - it('should call mutate and refresh on save callback from ExternalApiSelect dropdown', async () => { + it('should invalidate and refresh after saving from the API dropdown', async () => { const user = userEvent.setup() renderComponent() @@ -614,11 +631,13 @@ describe('ExternalKnowledgeBaseCreate', () => { const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] await modalCall.onSaveCallback() - expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() + expect(mockInvalidateQueries).toHaveBeenCalledWith({ + queryKey: externalKnowledgeApiQueryKey, + }) expect(mockRefresh).toHaveBeenCalled() }) - it('should call mutate on cancel callback from ExternalApiSelect dropdown', async () => { + it('should not invalidate after canceling from the API dropdown', async () => { const user = userEvent.setup() renderComponent() @@ -630,9 +649,8 @@ describe('ExternalKnowledgeBaseCreate', () => { // Get the callback from the modal call and invoke it const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] - modalCall.onCancelCallback() - - expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() + expect(modalCall.onCancelCallback).toBeUndefined() + expect(mockInvalidateQueries).not.toHaveBeenCalled() }) it('should close dropdown after selecting an API', async () => { diff --git a/web/app/components/datasets/list/__tests__/index.spec.tsx b/web/app/components/datasets/list/__tests__/index.spec.tsx index b787406e41a..eeaedba150d 100644 --- a/web/app/components/datasets/list/__tests__/index.spec.tsx +++ b/web/app/components/datasets/list/__tests__/index.spec.tsx @@ -126,15 +126,6 @@ const renderList = ( const render = (ui: ReactElement) => renderList(ui) const renderWithNuqs = renderList -// Mock external api panel context -const mockSetShowExternalApiPanel = vi.fn() -vi.mock('@/context/external-api-panel-context', () => ({ - useExternalApiPanel: () => ({ - showExternalApiPanel: false, - setShowExternalApiPanel: mockSetShowExternalApiPanel, - }), -})) - // Mock useDocumentTitle hook vi.mock('@/hooks/use-document-title', () => ({ default: vi.fn(), @@ -336,6 +327,24 @@ describe('List', () => { expect(onUrlUpdate.mock.calls.at(-1)?.[0].searchParams.get('view')).toBe('new') }) + it('should reset each view panel when its owning list unmounts', async () => { + const user = userEvent.setup() + mockConsoleState.knowledgeFsEnabled = true + renderWithNuqs() + + await user.click(screen.getByRole('button', { name: 'dataset.externalAPIPanelTitle' })) + expect(screen.getByTestId('external-api-panel')).toBeInTheDocument() + + await user.click(screen.getByRole('button', { name: 'dataset.newKnowledge.new' })) + expect(screen.queryByTestId('external-api-panel')).not.toBeInTheDocument() + + await user.click(screen.getByRole('button', { name: 'dataset.externalAPIPanelTitle' })) + expect(screen.getByTestId('external-api-panel')).toBeInTheDocument() + + await user.click(screen.getByRole('button', { name: 'dataset.newKnowledge.legacy' })) + expect(screen.queryByTestId('external-api-panel')).not.toBeInTheDocument() + }) + it('should restore the New Knowledge view from the URL', () => { mockConsoleState.knowledgeFsEnabled = true @@ -435,6 +444,7 @@ describe('List', () => { render() expect(screen.queryByText(/externalAPIPanelTitle/)).not.toBeInTheDocument() + expect(screen.queryByTestId('external-api-panel')).not.toBeInTheDocument() }) }) @@ -483,7 +493,7 @@ describe('List', () => { const button = screen.getByText(/externalAPIPanelTitle/) fireEvent.click(button) - expect(mockSetShowExternalApiPanel).toHaveBeenCalledWith(true) + expect(screen.getByTestId('external-api-panel')).toBeInTheDocument() }) it('should update search input value', () => { @@ -654,69 +664,15 @@ describe('List', () => { } }) - it('should show ExternalAPIPanel when showExternalApiPanel is true', async () => { - // Re-mock to show external API panel - vi.doMock('@/context/external-api-panel-context', () => ({ - useExternalApiPanel: () => ({ - showExternalApiPanel: true, - setShowExternalApiPanel: mockSetShowExternalApiPanel, - }), - })) + it('should close ExternalAPIPanel when onClose is called', () => { + render() - vi.resetModules() - const { default: ListComponent } = await import('../index') - - render() - - expect(screen.getByTestId('external-api-panel')).toBeInTheDocument() - expect(screen.getByTestId('external-api-panel')).toHaveAttribute( - 'data-can-manage-external-knowledge-api', - 'true', - ) - }) - - it('should not show ExternalAPIPanel without dataset.external.connect even when panel state is open', async () => { - mockConsoleState = { - isCurrentWorkspaceEditor: true, - isCurrentWorkspaceManager: true, - isCurrentWorkspaceOwner: true, - knowledgeFsEnabled: false, - workspacePermissionKeys: ['dataset.create_and_management'], - } - vi.doMock('@/context/external-api-panel-context', () => ({ - useExternalApiPanel: () => ({ - showExternalApiPanel: true, - setShowExternalApiPanel: mockSetShowExternalApiPanel, - }), - })) - - vi.resetModules() - const { default: ListComponent } = await import('../index') - - render() + fireEvent.click(screen.getByText(/externalAPIPanelTitle/)) + fireEvent.click(screen.getByText('Close Panel')) expect(screen.queryByTestId('external-api-panel')).not.toBeInTheDocument() }) - it('should close ExternalAPIPanel when onClose is called', async () => { - vi.doMock('@/context/external-api-panel-context', () => ({ - useExternalApiPanel: () => ({ - showExternalApiPanel: true, - setShowExternalApiPanel: mockSetShowExternalApiPanel, - }), - })) - - vi.resetModules() - const { default: ListComponent } = await import('../index') - - render() - - const closeButton = screen.getByText('Close Panel') - fireEvent.click(closeButton) - - expect(mockSetShowExternalApiPanel).toHaveBeenCalledWith(false) - }) - it('should show TagManagementModal when tag management is opened', () => { render() fireEvent.click(screen.getByText('Manage Tags')) diff --git a/web/app/components/datasets/list/index.tsx b/web/app/components/datasets/list/index.tsx index ed907c3b304..f4dc7cb2a8e 100644 --- a/web/app/components/datasets/list/index.tsx +++ b/web/app/components/datasets/list/index.tsx @@ -18,7 +18,6 @@ import { getStepByStepTourGuides, STEP_BY_STEP_TOUR_TARGETS, } from '@/app/components/step-by-step-tour/target-registry' -import { useExternalApiPanel } from '@/context/external-api-panel-context' import { workspacePermissionKeysAtom } from '@/context/permission-state' import { isCurrentWorkspaceOwnerAtom } from '@/context/workspace-state' import { NewKnowledgeList } from '@/features/new-rag/new-knowledge-list' @@ -50,7 +49,7 @@ function LegacyList({ const { push } = useRouter() const isCurrentWorkspaceOwner = useAtomValue(isCurrentWorkspaceOwnerAtom) const [showTagManagementModal, setShowTagManagementModal] = useState(false) - const { showExternalApiPanel, setShowExternalApiPanel } = useExternalApiPanel() + const [showExternalApiPanel, setShowExternalApiPanel] = useState(false) const [includeAll, { toggle: toggleIncludeAll }] = useBoolean(false) const invalidDatasetList = useInvalidDatasetList() useDocumentTitle(t(($) => $.knowledge, { ns: 'dataset' })) diff --git a/web/context/external-api-panel-context.tsx b/web/context/external-api-panel-context.tsx deleted file mode 100644 index 5c6f0ad738b..00000000000 --- a/web/context/external-api-panel-context.tsx +++ /dev/null @@ -1,29 +0,0 @@ -'use client' - -import * as React from 'react' -import { createContext, use, useState } from 'react' - -type ExternalApiPanelContextType = { - showExternalApiPanel: boolean - setShowExternalApiPanel: (show: boolean) => void -} - -const ExternalApiPanelContext = createContext(undefined) - -export const ExternalApiPanelProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const [showExternalApiPanel, setShowExternalApiPanel] = useState(false) - - return ( - - {children} - - ) -} - -export const useExternalApiPanel = () => { - const context = use(ExternalApiPanelContext) - if (context === undefined) - throw new Error('useExternalApiPanel must be used within an ExternalApiPanelProvider') - - return context -} diff --git a/web/context/external-knowledge-api-context.tsx b/web/context/external-knowledge-api-context.tsx deleted file mode 100644 index 0e3f40809c9..00000000000 --- a/web/context/external-knowledge-api-context.tsx +++ /dev/null @@ -1,57 +0,0 @@ -'use client' - -import type { FC, ReactNode } from 'react' -import type { ExternalAPIItem, ExternalAPIListResponse } from '@/models/datasets' -import { createContext, use, useCallback, useMemo } from 'react' -import { useExternalKnowledgeApiList } from '@/service/knowledge/use-dataset' - -type ExternalKnowledgeApiContextType = { - externalKnowledgeApiList: ExternalAPIItem[] - mutateExternalKnowledgeApis: () => Promise - isLoading: boolean -} - -const ExternalKnowledgeApiContext = createContext( - undefined, -) - -type ExternalKnowledgeApiProviderProps = { - children: ReactNode - enabled?: boolean -} - -export const ExternalKnowledgeApiProvider: FC = ({ - children, - enabled = true, -}) => { - const { data, refetch, isLoading } = useExternalKnowledgeApiList({ enabled }) - - const mutateExternalKnowledgeApis = useCallback(() => { - if (!enabled) return Promise.resolve(undefined) - - return refetch().then((res) => res.data) - }, [enabled, refetch]) - - const contextValue = useMemo( - () => ({ - externalKnowledgeApiList: data?.data || [], - mutateExternalKnowledgeApis, - isLoading, - }), - [data, mutateExternalKnowledgeApis, isLoading], - ) - - return ( - - {children} - - ) -} - -export const useExternalKnowledgeApi = () => { - const context = use(ExternalKnowledgeApiContext) - if (context === undefined) - throw new Error('useExternalKnowledgeApi must be used within a ExternalKnowledgeApiProvider') - - return context -} diff --git a/web/features/new-rag/__tests__/new-knowledge-list.spec.tsx b/web/features/new-rag/__tests__/new-knowledge-list.spec.tsx index fe0acf093cd..1b98fbf24d6 100644 --- a/web/features/new-rag/__tests__/new-knowledge-list.spec.tsx +++ b/web/features/new-rag/__tests__/new-knowledge-list.spec.tsx @@ -16,10 +16,6 @@ type ListKnowledgeSpacesInfiniteOptions = { } } -const externalApiPanelMock = vi.hoisted(() => ({ - open: false, - setOpen: vi.fn(), -})) const toastInfoMock = vi.hoisted(() => vi.fn()) vi.mock('@langgenius/dify-ui/toast', () => ({ @@ -46,13 +42,6 @@ const permissionStateMock = vi.hoisted(() => ({ workspacePermissionKeysAtom: Symbol('workspacePermissionKeysAtom'), })) -vi.mock('@/context/external-api-panel-context', () => ({ - useExternalApiPanel: () => ({ - showExternalApiPanel: externalApiPanelMock.open, - setShowExternalApiPanel: externalApiPanelMock.setOpen, - }), -})) - vi.mock('@/service/knowledge/use-dataset', () => ({ useDatasetApiBaseUrl: () => ({ data: { api_base_url: 'https://api.example.com' } }), })) @@ -62,7 +51,14 @@ vi.mock('@/app/components/datasets/extra-info/service-api', () => ({ })) vi.mock('@/app/components/datasets/external-api/external-api-panel', () => ({ - default: () =>
external API panel
, + default: ({ onClose }: { onClose: () => void }) => ( +
+ external API panel + +
+ ), })) vi.mock('@tanstack/react-query', async (importOriginal) => { @@ -109,7 +105,6 @@ const setResolvedPage = (items: KnowledgeSpaceList['items'] = []) => { describe('NewKnowledgeList', () => { beforeEach(() => { vi.clearAllMocks() - externalApiPanelMock.open = false queryMock.data = undefined queryMock.error = null queryMock.hasNextPage = false @@ -219,7 +214,9 @@ describe('NewKnowledgeList', () => { renderWithNuqs() await user.click(screen.getByRole('button', { name: 'dataset.externalAPIPanelTitle' })) - expect(externalApiPanelMock.setOpen).toHaveBeenCalledWith(true) + expect(screen.getByText('external API panel')).toBeInTheDocument() + await user.click(screen.getByRole('button', { name: 'close external API panel' })) + expect(screen.queryByText('external API panel')).not.toBeInTheDocument() expect(screen.getByRole('button', { name: 'dataset.serviceApi.title' })).toBeInTheDocument() const tags = screen.getByRole('button', { name: 'dataset.newKnowledge.tags' }) @@ -296,6 +293,10 @@ describe('NewKnowledgeList', () => { expect( screen.queryByRole('link', { name: /common\.operation\.create/ }), ).not.toBeInTheDocument() + expect( + screen.queryByRole('button', { name: 'dataset.externalAPIPanelTitle' }), + ).not.toBeInTheDocument() + expect(screen.queryByText('external API panel')).not.toBeInTheDocument() expect(screen.getByText('dataset.newKnowledge.readOnlyEmpty')).toBeInTheDocument() }) diff --git a/web/features/new-rag/new-knowledge-list.tsx b/web/features/new-rag/new-knowledge-list.tsx index c63f44dc059..eadea7beafb 100644 --- a/web/features/new-rag/new-knowledge-list.tsx +++ b/web/features/new-rag/new-knowledge-list.tsx @@ -9,7 +9,6 @@ import { useTranslation } from 'react-i18next' import { SearchInput } from '@/app/components/base/search-input' import ExternalAPIPanel from '@/app/components/datasets/external-api/external-api-panel' import ServiceApi from '@/app/components/datasets/extra-info/service-api' -import { useExternalApiPanel } from '@/context/external-api-panel-context' import { workspacePermissionKeysAtom } from '@/context/permission-state' import Link from '@/next/link' import { consoleQuery } from '@/service/client' @@ -60,7 +59,7 @@ export function NewKnowledgeList({ const { t } = useTranslation('dataset') const { t: tCommon } = useTranslation('common') const { data: apiBaseInfo } = useDatasetApiBaseUrl() - const { showExternalApiPanel, setShowExternalApiPanel } = useExternalApiPanel() + const [showExternalApiPanel, setShowExternalApiPanel] = useState(false) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const canCreate = hasPermission(workspacePermissionKeys, 'dataset.create_and_management') const canConnect = hasPermission(workspacePermissionKeys, 'dataset.external.connect') diff --git a/web/models/datasets.ts b/web/models/datasets.ts index d6fe1f6c571..5d4503e932a 100644 --- a/web/models/datasets.ts +++ b/web/models/datasets.ts @@ -223,14 +223,6 @@ export type DataSetListResponse = { total: number } -export type ExternalAPIListResponse = { - data: ExternalAPIItem[] - has_more: boolean - limit: number - page: number - total: number -} - export type QA = { question: string answer: string diff --git a/web/service/knowledge/use-dataset.ts b/web/service/knowledge/use-dataset.ts index f2919db02fd..d4f42db4859 100644 --- a/web/service/knowledge/use-dataset.ts +++ b/web/service/knowledge/use-dataset.ts @@ -6,7 +6,6 @@ import type { DatasetListRequest, DataSetListResponse, ErrorDocsResponse, - ExternalAPIListResponse, FetchDatasetsParams, HitTestingRecordsResponse, IndexingStatusBatchRequest, @@ -189,14 +188,6 @@ export const useInvalidateDatasetApiKeys = () => { } } -export const useExternalKnowledgeApiList = (options?: { enabled?: boolean }) => { - return useQuery({ - queryKey: [NAME_SPACE, 'external-knowledge-api'], - queryFn: () => get('/datasets/external-knowledge-api'), - enabled: options?.enabled ?? true, - }) -} - export const useDatasetTestingRecords = ( datasetId?: string, params?: { page: number; limit: number },