From f8d7d07c1397c3524d1e7f691d76a1fb69596316 Mon Sep 17 00:00:00 2001 From: twwu Date: Wed, 30 Jul 2025 15:19:10 +0800 Subject: [PATCH] feat: Introduce CredentialSelector component and remove WorkspaceSelector --- .../base/notion-page-selector/base.tsx | 158 +++++++------- .../credential-selector/index.tsx | 113 ++++++++++ .../workspace-selector/index.tsx | 79 ------- web/app/components/datasets/create/index.tsx | 203 +++++++++--------- .../datasets/create/step-one/index.tsx | 30 ++- .../datasets/create/top-bar/index.tsx | 2 +- .../datasets/create/website/index.module.css | 2 +- .../datasets/create/website/index.tsx | 79 +++---- .../datasets/create/website/no-data.tsx | 10 +- .../hooks/use-data-source-auth-update.ts | 3 + .../data-source-page-new/types.ts | 2 + .../data-source-page/index.module.css | 0 .../data-source-page/index.tsx | 20 -- web/service/knowledge/use-import.ts | 22 +- web/service/use-common.ts | 12 -- web/service/use-datasource.ts | 14 ++ 16 files changed, 398 insertions(+), 351 deletions(-) create mode 100644 web/app/components/base/notion-page-selector/credential-selector/index.tsx delete mode 100644 web/app/components/base/notion-page-selector/workspace-selector/index.tsx delete mode 100644 web/app/components/header/account-setting/data-source-page/index.module.css delete mode 100644 web/app/components/header/account-setting/data-source-page/index.tsx diff --git a/web/app/components/base/notion-page-selector/base.tsx b/web/app/components/base/notion-page-selector/base.tsx index a36dee0e10..cf5e7eebe4 100644 --- a/web/app/components/base/notion-page-selector/base.tsx +++ b/web/app/components/base/notion-page-selector/base.tsx @@ -1,5 +1,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react' -import WorkspaceSelector from './workspace-selector' +import type { NotionCredential } from './credential-selector' +import WorkspaceSelector from './credential-selector' import SearchInput from './search-input' import PageSelector from './page-selector' import type { DataSourceNotionPageMap, DataSourceNotionWorkspace, NotionPage } from '@/models/common' @@ -7,6 +8,7 @@ import { useModalContextSelector } from '@/context/modal-context' import NotionConnector from '../notion-connector' import { usePreImportNotionPages } from '@/service/knowledge/use-import' import Header from '../../datasets/create/website/base/header' +import type { DataSourceCredential } from '../../header/account-setting/data-source-page-new/types' type NotionPageSelectorProps = { value?: string[] @@ -15,6 +17,7 @@ type NotionPageSelectorProps = { previewPageId?: string onPreview?: (selectedPage: NotionPage) => void datasetId?: string + credentialList: DataSourceCredential[] } const NotionPageSelector = ({ @@ -24,22 +27,35 @@ const NotionPageSelector = ({ previewPageId, onPreview, datasetId = '', + credentialList, }: NotionPageSelectorProps) => { - const { data, refetch } = usePreImportNotionPages({ url: '/notion/pre-import/pages', datasetId }) - const [prevData, setPrevData] = useState(data) const [searchValue, setSearchValue] = useState('') - const [currentWorkspaceId, setCurrentWorkspaceId] = useState('') const setShowAccountSettingModal = useModalContextSelector(s => s.setShowAccountSettingModal) - const notionWorkspaces = useMemo(() => { - return data?.notion_info || [] - }, [data?.notion_info]) - const firstWorkspaceId = notionWorkspaces[0]?.workspace_id - const currentWorkspace = notionWorkspaces.find(workspace => workspace.workspace_id === currentWorkspaceId) + const notionCredentials = useMemo((): NotionCredential[] => { + return credentialList.map((item) => { + return { + credentialId: item.id, + credentialName: item.name, + workspaceIcon: item.credential.workspace_icon, + workspaceName: item.credential.workspace_name, + } + }) + }, [credentialList]) + const [currentCredential, setCurrentCredential] = useState(notionCredentials[0]) + + useEffect(() => { + const credential = notionCredentials.find(item => item.credentialId === currentCredential?.credentialId) + if (!credential) + setCurrentCredential(notionCredentials[0]) + }, [notionCredentials]) + + const { data } = usePreImportNotionPages({ datasetId, credentialId: currentCredential.credentialId || '' }) const getPagesMapAndSelectedPagesId: [DataSourceNotionPageMap, Set, Set] = useMemo(() => { const selectedPagesId = new Set() const boundPagesId = new Set() + const notionWorkspaces = data?.notion_info || [] const pagesMap = notionWorkspaces.reduce((prev: DataSourceNotionPageMap, next: DataSourceNotionWorkspace) => { next.pages.forEach((page) => { if (page.is_bound) { @@ -55,88 +71,86 @@ const NotionPageSelector = ({ return prev }, {}) return [pagesMap, selectedPagesId, boundPagesId] - }, [notionWorkspaces]) + }, [data?.notion_info]) + const defaultSelectedPagesId = [...Array.from(getPagesMapAndSelectedPagesId[1]), ...(value || [])] const [selectedPagesId, setSelectedPagesId] = useState>(new Set(defaultSelectedPagesId)) - if (prevData !== data) { - setPrevData(data) + useEffect(() => { setSelectedPagesId(new Set(defaultSelectedPagesId)) - } + }, [data]) const handleSearchValueChange = useCallback((value: string) => { setSearchValue(value) }, []) - const handleSelectWorkspace = useCallback((workspaceId: string) => { - setCurrentWorkspaceId(workspaceId) + + const handleSelectCredential = useCallback((credentialId: string) => { + const credential = notionCredentials.find(item => item.credentialId === credentialId)! + setCurrentCredential(credential) }, []) - const handleSelectPages = (newSelectedPagesId: Set) => { + + const handleSelectPages = useCallback((newSelectedPagesId: Set) => { const selectedPages = Array.from(newSelectedPagesId).map(pageId => getPagesMapAndSelectedPagesId[0][pageId]) setSelectedPagesId(new Set(Array.from(newSelectedPagesId))) onSelect(selectedPages) - } - const handlePreviewPage = (previewPageId: string) => { + }, [getPagesMapAndSelectedPagesId, onSelect]) + + const handlePreviewPage = useCallback((previewPageId: string) => { if (onPreview) onPreview(getPagesMapAndSelectedPagesId[0][previewPageId]) - } - - useEffect(() => { - setCurrentWorkspaceId(firstWorkspaceId) - }, [firstWorkspaceId]) + }, [getPagesMapAndSelectedPagesId, onSelect, onPreview]) const handleConfigureNotion = useCallback(() => { - setShowAccountSettingModal({ payload: 'data-source', onCancelCallback: refetch }) - }, [setShowAccountSettingModal, refetch]) + setShowAccountSettingModal({ payload: 'data-source' }) + }, [setShowAccountSettingModal]) + + if (!data) { + return ( + + ) + } return ( - <> - { - data?.notion_info?.length - ? ( -
-
-
-
-
- -
- -
-
- -
-
-
- ) - : ( - - ) - } - +
+
+
+
+
+ +
+ +
+
+ +
+
+
) } diff --git a/web/app/components/base/notion-page-selector/credential-selector/index.tsx b/web/app/components/base/notion-page-selector/credential-selector/index.tsx new file mode 100644 index 0000000000..f0ec399544 --- /dev/null +++ b/web/app/components/base/notion-page-selector/credential-selector/index.tsx @@ -0,0 +1,113 @@ +'use client' +import { useTranslation } from 'react-i18next' +import React, { Fragment, useMemo } from 'react' +import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react' +import { RiArrowDownSLine } from '@remixicon/react' +import NotionIcon from '../../notion-icon' + +export type NotionCredential = { + credentialId: string + credentialName: string + workspaceIcon?: string + workspaceName?: string +} + +type CredentialSelectorProps = { + value: string + items: NotionCredential[] + onSelect: (v: string) => void +} + +const CredentialSelector = ({ + value, + items, + onSelect, +}: CredentialSelectorProps) => { + const { t } = useTranslation() + const currentCredential = items.find(item => item.credentialId === value)! + + const getDisplayName = (item: NotionCredential) => { + return item.workspaceName || t('datasetPipeline.credentialSelector.name', { + credentialName: item.credentialName, + pluginName: 'Notion', + }) + } + + const currentDisplayName = useMemo(() => { + return getDisplayName(currentCredential) + }, [currentCredential]) + + return ( + + { + ({ open }) => ( + <> + + +
+ {currentDisplayName} +
+ +
+ + +
+ { + items.map((item) => { + const displayName = getDisplayName(item) + return ( + +
onSelect(item.credentialId)} + > + +
+ {displayName} +
+ {/* // ?Cannot get page length with new auth system */} + {/*
+ {item.pages.length} {t('common.dataSource.notion.selector.pageSelected')} +
*/} +
+
+ ) + }) + } +
+
+
+ + ) + } +
+ ) +} + +export default React.memo(CredentialSelector) diff --git a/web/app/components/base/notion-page-selector/workspace-selector/index.tsx b/web/app/components/base/notion-page-selector/workspace-selector/index.tsx deleted file mode 100644 index 1fb55598e3..0000000000 --- a/web/app/components/base/notion-page-selector/workspace-selector/index.tsx +++ /dev/null @@ -1,79 +0,0 @@ -'use client' -import { useTranslation } from 'react-i18next' -import { Fragment } from 'react' -import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react' -import { RiArrowDownSLine } from '@remixicon/react' -import NotionIcon from '../../notion-icon' -import type { DataSourceNotionWorkspace } from '@/models/common' - -type WorkspaceSelectorProps = { - value: string - items: Omit[] - onSelect: (v: string) => void -} -export default function WorkspaceSelector({ - value, - items, - onSelect, -}: WorkspaceSelectorProps) { - const { t } = useTranslation() - const currentWorkspace = items.find(item => item.workspace_id === value) - - return ( - - { - ({ open }) => ( - <> - - -
{currentWorkspace?.workspace_name}
- -
- - -
- { - items.map(item => ( - -
onSelect(item.workspace_id)} - > - -
{item.workspace_name}
-
- {item.pages.length} {t('common.dataSource.notion.selector.pageSelected')} -
-
-
- )) - } -
-
-
- - ) - } -
- ) -} diff --git a/web/app/components/datasets/create/index.tsx b/web/app/components/datasets/create/index.tsx index da51919062..41ee1b0820 100644 --- a/web/app/components/datasets/create/index.tsx +++ b/web/app/components/datasets/create/index.tsx @@ -1,5 +1,5 @@ 'use client' -import React, { useCallback, useEffect, useState } from 'react' +import React, { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import AppUnavailable from '../../base/app-unavailable' import { ModelTypeEnum } from '../../header/account-setting/model-provider-page/declarations' @@ -8,12 +8,14 @@ import StepTwo from './step-two' import StepThree from './step-three' import { TopBar } from './top-bar' import { DataSourceType } from '@/models/datasets' -import type { CrawlOptions, CrawlResultItem, DataSet, FileItem, createDocumentResponse } from '@/models/datasets' -import { fetchDataSource } from '@/service/common' +import type { CrawlOptions, CrawlResultItem, FileItem, createDocumentResponse } from '@/models/datasets' import { DataSourceProvider, type NotionPage } from '@/models/common' import { useModalContext } from '@/context/modal-context' import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks' -import { useDatasetDetail } from '@/service/knowledge/use-dataset' +import { useGetDefaultDataSourceListAuth } from '@/service/use-datasource' +import produce from 'immer' +import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' +import Loading from '@/app/components/base/loading' type DatasetUpdateFormProps = { datasetId?: string @@ -32,57 +34,51 @@ const DEFAULT_CRAWL_OPTIONS: CrawlOptions = { const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => { const { t } = useTranslation() const { setShowAccountSettingModal } = useModalContext() - const [hasConnection, setHasConnection] = useState(true) + const datasetDetail = useDatasetDetailContextWithSelector(state => state.dataset) + const { data: embeddingsDefaultModel } = useDefaultModel(ModelTypeEnum.textEmbedding) + const [dataSourceType, setDataSourceType] = useState(DataSourceType.FILE) const [step, setStep] = useState(1) const [indexingTypeCache, setIndexTypeCache] = useState('') const [retrievalMethodCache, setRetrievalMethodCache] = useState('') const [fileList, setFiles] = useState([]) const [result, setResult] = useState() - const { data: embeddingsDefaultModel } = useDefaultModel(ModelTypeEnum.textEmbedding) - const [notionPages, setNotionPages] = useState([]) - const updateNotionPages = (value: NotionPage[]) => { - setNotionPages(value) - } - const [websitePages, setWebsitePages] = useState([]) const [crawlOptions, setCrawlOptions] = useState(DEFAULT_CRAWL_OPTIONS) - - const updateFileList = (preparedFiles: FileItem[]) => { - setFiles(preparedFiles) - } const [websiteCrawlProvider, setWebsiteCrawlProvider] = useState(DataSourceProvider.fireCrawl) const [websiteCrawlJobId, setWebsiteCrawlJobId] = useState('') - const updateFile = (fileItem: FileItem, progress: number, list: FileItem[]) => { + const updateNotionPages = useCallback((value: NotionPage[]) => { + setNotionPages(value) + }, []) + + const updateFileList = useCallback((preparedFiles: FileItem[]) => { + setFiles(preparedFiles) + }, []) + + const updateFile = useCallback((fileItem: FileItem, progress: number, list: FileItem[]) => { const targetIndex = list.findIndex(file => file.fileID === fileItem.fileID) - list[targetIndex] = { - ...list[targetIndex], - progress, - } - setFiles([...list]) - // use follow code would cause dirty list update problem - // const newList = list.map((file) => { - // if (file.fileID === fileItem.fileID) { - // return { - // ...fileItem, - // progress, - // } - // } - // return file - // }) - // setFiles(newList) - } - const updateIndexingTypeCache = (type: string) => { + const newList = produce(list, (draft) => { + draft[targetIndex] = { + ...draft[targetIndex], + progress, + } + }) + setFiles(newList) + }, []) + + const updateIndexingTypeCache = useCallback((type: string) => { setIndexTypeCache(type) - } - const updateResultCache = (res?: createDocumentResponse) => { + }, []) + + const updateResultCache = useCallback((res?: createDocumentResponse) => { setResult(res) - } - const updateRetrievalMethodCache = (method: string) => { + }, []) + + const updateRetrievalMethodCache = useCallback((method: string) => { setRetrievalMethodCache(method) - } + }, []) const nextStep = useCallback(() => { setStep(step + 1) @@ -92,75 +88,80 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => { setStep(step + delta) }, [step, setStep]) - const checkNotionConnection = async () => { - const { data } = await fetchDataSource({ url: '/data-source/integrates' }) - const hasConnection = data.filter(item => item.provider === 'notion') || [] - setHasConnection(hasConnection.length > 0) - } + const { + data: dataSourceList, + isLoading: isLoadingAuthedDataSourceList, + isError: fetchingAuthedDataSourceListError, + } = useGetDefaultDataSourceListAuth() - useEffect(() => { - checkNotionConnection() - }, []) - - const [detail, setDetail] = useState(null) - - const { data: datasetDetail, error: fetchDatasetDetailError } = useDatasetDetail(datasetId || '') - useEffect(() => { - if (!datasetDetail) return - setDetail(datasetDetail) - }, [datasetDetail]) - - if (fetchDatasetDetailError) + if (fetchingAuthedDataSourceListError) return return (
- {step === 1 && setShowAccountSettingModal({ payload: 'data-source' })} - datasetId={datasetId} - dataSourceType={dataSourceType} - dataSourceTypeDisable={!!detail?.data_source_type} - changeType={setDataSourceType} - files={fileList} - updateFile={updateFile} - updateFileList={updateFileList} - notionPages={notionPages} - updateNotionPages={updateNotionPages} - onStepChange={nextStep} - websitePages={websitePages} - updateWebsitePages={setWebsitePages} - onWebsiteCrawlProviderChange={setWebsiteCrawlProvider} - onWebsiteCrawlJobIdChange={setWebsiteCrawlJobId} - crawlOptions={crawlOptions} - onCrawlOptionsChange={setCrawlOptions} - />} - {(step === 2 && (!datasetId || (datasetId && !!detail))) && setShowAccountSettingModal({ payload: 'provider' })} - indexingType={detail?.indexing_technique} - datasetId={datasetId} - dataSourceType={dataSourceType} - files={fileList.map(file => file.file)} - notionPages={notionPages} - websitePages={websitePages} - websiteCrawlProvider={websiteCrawlProvider} - websiteCrawlJobId={websiteCrawlJobId} - onStepChange={changeStep} - updateIndexingTypeCache={updateIndexingTypeCache} - updateRetrievalMethodCache={updateRetrievalMethodCache} - updateResultCache={updateResultCache} - crawlOptions={crawlOptions} - />} - {step === 3 && } + { + isLoadingAuthedDataSourceList && ( + + ) + } + { + !isLoadingAuthedDataSourceList && ( + <> + {step === 1 && ( + setShowAccountSettingModal({ payload: 'data-source' })} + datasetId={datasetId} + dataSourceType={dataSourceType} + dataSourceTypeDisable={!!datasetDetail?.data_source_type} + changeType={setDataSourceType} + files={fileList} + updateFile={updateFile} + updateFileList={updateFileList} + notionPages={notionPages} + updateNotionPages={updateNotionPages} + onStepChange={nextStep} + websitePages={websitePages} + updateWebsitePages={setWebsitePages} + onWebsiteCrawlProviderChange={setWebsiteCrawlProvider} + onWebsiteCrawlJobIdChange={setWebsiteCrawlJobId} + crawlOptions={crawlOptions} + onCrawlOptionsChange={setCrawlOptions} + /> + )} + {(step === 2 && (!datasetId || (datasetId && !!datasetDetail))) && ( + setShowAccountSettingModal({ payload: 'provider' })} + indexingType={datasetDetail?.indexing_technique} + datasetId={datasetId} + dataSourceType={dataSourceType} + files={fileList.map(file => file.file)} + notionPages={notionPages} + websitePages={websitePages} + websiteCrawlProvider={websiteCrawlProvider} + websiteCrawlJobId={websiteCrawlJobId} + onStepChange={changeStep} + updateIndexingTypeCache={updateIndexingTypeCache} + updateRetrievalMethodCache={updateRetrievalMethodCache} + updateResultCache={updateResultCache} + crawlOptions={crawlOptions} + /> + )} + {step === 3 && ( + + )} + + ) + }
) diff --git a/web/app/components/datasets/create/step-one/index.tsx b/web/app/components/datasets/create/step-one/index.tsx index 3e93442e6c..a89322160a 100644 --- a/web/app/components/datasets/create/step-one/index.tsx +++ b/web/app/components/datasets/create/step-one/index.tsx @@ -15,18 +15,18 @@ import type { DataSourceProvider, NotionPage } from '@/models/common' import { DataSourceType } from '@/models/datasets' import Button from '@/app/components/base/button' import { NotionPageSelector } from '@/app/components/base/notion-page-selector' -import { useDatasetDetailContext } from '@/context/dataset-detail' +import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { useProviderContext } from '@/context/provider-context' import VectorSpaceFull from '@/app/components/billing/vector-space-full' import classNames from '@/utils/classnames' import { ENABLE_WEBSITE_FIRECRAWL, ENABLE_WEBSITE_JINAREADER, ENABLE_WEBSITE_WATERCRAWL } from '@/config' import NotionConnector from '@/app/components/base/notion-connector' +import type { DataSourceAuth } from '@/app/components/header/account-setting/data-source-page-new/types' type IStepOneProps = { datasetId?: string dataSourceType?: DataSourceType dataSourceTypeDisable: boolean - hasConnection: boolean onSetting: () => void files: FileItem[] updateFileList: (files: FileItem[]) => void @@ -41,6 +41,7 @@ type IStepOneProps = { onWebsiteCrawlJobIdChange: (jobId: string) => void crawlOptions: CrawlOptions onCrawlOptionsChange: (payload: CrawlOptions) => void + authedDataSourceList: DataSourceAuth[] } const StepOne = ({ @@ -48,7 +49,6 @@ const StepOne = ({ dataSourceType: inCreatePageDataSourceType, dataSourceTypeDisable, changeType, - hasConnection, onSetting, onStepChange, files, @@ -62,8 +62,9 @@ const StepOne = ({ onWebsiteCrawlJobIdChange, crawlOptions, onCrawlOptionsChange, + authedDataSourceList, }: IStepOneProps) => { - const { dataset } = useDatasetDetailContext() + const dataset = useDatasetDetailContextWithSelector(state => state.dataset) const [showModal, setShowModal] = useState(false) const [currentFile, setCurrentFile] = useState() const [currentNotionPage, setCurrentNotionPage] = useState() @@ -114,6 +115,17 @@ const StepOne = ({ return isShowVectorSpaceFull }, [files, isShowVectorSpaceFull]) + const isNotionAuthed = useMemo(() => { + if (!authedDataSourceList) return false + const notionSource = authedDataSourceList.find(item => item.provider === 'notion_datasource') + if (!notionSource) return false + return notionSource.credentials_list.length > 0 + }, [authedDataSourceList]) + + const notionCredentialList = useMemo(() => { + return authedDataSourceList.find(item => item.provider === 'notion_datasource')?.credentials_list || [] + }, [authedDataSourceList]) + return (
@@ -221,7 +233,6 @@ const StepOne = ({
)}
- {/* */}
)}
- {/* */}
{isShowVectorSpaceFull && ( @@ -280,7 +293,6 @@ const StepOne = ({
)}
- {/* */} } - {ENABLE_WEBSITE_FIRECRAWL && } @@ -115,9 +97,12 @@ const Website: FC = ({ : `system-sm-regular border border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs hover:shadow-shadow-shadow-3`, )} - onClick={() => setSelectedProvider(DataSourceProvider.waterCrawl)} + onClick={() => { + setSelectedProvider(DataSourceProvider.waterCrawl) + onCrawlProviderChange(DataSourceProvider.waterCrawl) + }} > - + WaterCrawl }
@@ -153,7 +138,7 @@ const Website: FC = ({ /> )} {!source && ( - + )} ) diff --git a/web/app/components/datasets/create/website/no-data.tsx b/web/app/components/datasets/create/website/no-data.tsx index 1db83a7417..dcd557c809 100644 --- a/web/app/components/datasets/create/website/no-data.tsx +++ b/web/app/components/datasets/create/website/no-data.tsx @@ -5,8 +5,8 @@ import { useTranslation } from 'react-i18next' import s from './index.module.css' import { Icon3Dots } from '@/app/components/base/icons/src/vender/line/others' import Button from '@/app/components/base/button' -import { DataSourceProvider } from '@/models/common' import { ENABLE_WEBSITE_FIRECRAWL, ENABLE_WEBSITE_JINAREADER, ENABLE_WEBSITE_WATERCRAWL } from '@/config' +import { DataSourceProvider } from '@/models/common' const I18N_PREFIX = 'datasetCreation.stepOne.website' @@ -21,7 +21,11 @@ const NoData: FC = ({ }) => { const { t } = useTranslation() - const providerConfig = { + const providerConfig: Record = { [DataSourceProvider.jinaReader]: ENABLE_WEBSITE_JINAREADER ? { emoji: , title: t(`${I18N_PREFIX}.jinaReaderNotConfigured`), @@ -39,7 +43,7 @@ const NoData: FC = ({ } : null, } - const currentProvider = providerConfig[provider] || providerConfig[DataSourceProvider.jinaReader] + const currentProvider = providerConfig[provider] || providerConfig.jinareader if (!currentProvider) return null diff --git a/web/app/components/header/account-setting/data-source-page-new/hooks/use-data-source-auth-update.ts b/web/app/components/header/account-setting/data-source-page-new/hooks/use-data-source-auth-update.ts index 46d383e331..beda9fdf24 100644 --- a/web/app/components/header/account-setting/data-source-page-new/hooks/use-data-source-auth-update.ts +++ b/web/app/components/header/account-setting/data-source-page-new/hooks/use-data-source-auth-update.ts @@ -1,12 +1,15 @@ import { useCallback } from 'react' import { useInvalidDataSourceListAuth } from '@/service/use-datasource' +import { useInvalidDefaultDataSourceListAuth } from '@/service/use-datasource' import { useInvalidDataSourceList } from '@/service/use-pipeline' export const useDataSourceAuthUpdate = () => { const invalidateDataSourceListAuth = useInvalidDataSourceListAuth() + const invalidDefaultDataSourceListAuth = useInvalidDefaultDataSourceListAuth() const invalidateDataSourceList = useInvalidDataSourceList() const handleAuthUpdate = useCallback(() => { invalidateDataSourceListAuth() + invalidDefaultDataSourceListAuth() invalidateDataSourceList() }, [invalidateDataSourceListAuth, invalidateDataSourceList]) diff --git a/web/app/components/header/account-setting/data-source-page-new/types.ts b/web/app/components/header/account-setting/data-source-page-new/types.ts index 8812b9a045..ce34498cf0 100644 --- a/web/app/components/header/account-setting/data-source-page-new/types.ts +++ b/web/app/components/header/account-setting/data-source-page-new/types.ts @@ -9,6 +9,8 @@ export type DataSourceCredential = { type: CredentialTypeEnum name: string id: string + is_default: boolean + avatar_url: string } export type DataSourceAuth = { author: string diff --git a/web/app/components/header/account-setting/data-source-page/index.module.css b/web/app/components/header/account-setting/data-source-page/index.module.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/web/app/components/header/account-setting/data-source-page/index.tsx b/web/app/components/header/account-setting/data-source-page/index.tsx deleted file mode 100644 index fb13813d70..0000000000 --- a/web/app/components/header/account-setting/data-source-page/index.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import useSWR from 'swr' -import DataSourceNotion from './data-source-notion' -import DataSourceWebsite from './data-source-website' -import { fetchDataSource } from '@/service/common' -import { DataSourceProvider } from '@/models/common' -import { ENABLE_WEBSITE_FIRECRAWL, ENABLE_WEBSITE_JINAREADER, ENABLE_WEBSITE_WATERCRAWL } from '@/config' - -export default function DataSourcePage() { - const { data } = useSWR({ url: 'data-source/integrates' }, fetchDataSource) - const notionWorkspaces = data?.data.filter(item => item.provider === 'notion') || [] - - return ( -
- - {ENABLE_WEBSITE_JINAREADER && } - {ENABLE_WEBSITE_FIRECRAWL && } - {ENABLE_WEBSITE_WATERCRAWL && } -
- ) -} diff --git a/web/service/knowledge/use-import.ts b/web/service/knowledge/use-import.ts index cdbf31a67c..f169b0c468 100644 --- a/web/service/knowledge/use-import.ts +++ b/web/service/knowledge/use-import.ts @@ -1,16 +1,26 @@ import { useQuery } from '@tanstack/react-query' -import { preImportNotionPages } from '../datasets' +import { get } from '../base' +import type { DataSourceNotionWorkspace } from '@/models/common' type PreImportNotionPagesParams = { - url: string - datasetId?: string + credentialId: string + datasetId: string } -export const usePreImportNotionPages = ({ datasetId }: PreImportNotionPagesParams) => { +export const usePreImportNotionPages = ({ + credentialId, + datasetId, +}: PreImportNotionPagesParams) => { return useQuery({ - queryKey: ['notion-pre-import-pages'], + queryKey: ['notion-pre-import-pages', credentialId, datasetId], queryFn: async () => { - return preImportNotionPages({ url: '/notion/pre-import/pages', datasetId }) + return get<{ notion_info: DataSourceNotionWorkspace[] }>('/notion/pre-import/pages', { + params: { + dataset_id: datasetId, + credential_id: credentialId, + }, + }) }, + retry: 0, }) } diff --git a/web/service/use-common.ts b/web/service/use-common.ts index 167cf4e486..ae9300ef57 100644 --- a/web/service/use-common.ts +++ b/web/service/use-common.ts @@ -1,6 +1,5 @@ import { get, post } from './base' import type { - DataSourceNotion, FileUploadConfigResponse, Member, StructuredOutputRulesRequestBody, @@ -37,17 +36,6 @@ export const useFileSupportTypes = () => { }) } -type DataSourcesResponse = { - data: DataSourceNotion[] -} - -export const useDataSources = () => { - return useQuery({ - queryKey: [NAME_SPACE, 'data-sources'], - queryFn: () => get('/data-source/integrates'), - }) -} - type MemberResponse = { accounts: Member[] | null } diff --git a/web/service/use-datasource.ts b/web/service/use-datasource.ts index fbf5c3a649..cbaa14a7e0 100644 --- a/web/service/use-datasource.ts +++ b/web/service/use-datasource.ts @@ -17,3 +17,17 @@ export const useInvalidDataSourceListAuth = ( ) => { return useInvalid([NAME_SPACE, 'list']) } + +// !This hook is used for fetching the default data source list, which will be legacy and deprecated in the near future. +export const useGetDefaultDataSourceListAuth = () => { + return useQuery({ + queryKey: [NAME_SPACE, 'default-list'], + queryFn: () => get<{ result: DataSourceAuth[] }>('/auth/plugin/datasource/default-list'), + retry: 0, + }) +} + +export const useInvalidDefaultDataSourceListAuth = ( +) => { + return useInvalid([NAME_SPACE, 'default-list']) +}