import type { ReactNode } from 'react' import { useSuspenseQuery } from '@tanstack/react-query' import { memo, useCallback, useMemo, useState } from 'react' import { Trans, useTranslation } from 'react-i18next' import { SearchInput } from '@/app/components/base/search-input' import { SkeletonContainer, SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton' import { usePluginsWithLatestVersion } from '@/app/components/plugins/hooks' import { usePluginSettingsAccess } from '@/app/components/plugins/plugin-page/use-reference-setting' import { PluginCategoryEnum } from '@/app/components/plugins/types' import { STEP_BY_STEP_TOUR_TARGETS } from '@/app/components/step-by-step-tour/target-registry' import { systemFeaturesQueryOptions } from '@/features/system-features/client' import { useRenderI18nObject } from '@/hooks/use-i18n' import { useGetDataSourceListAuth, useInvalidDataSourceListAuth } from '@/service/use-datasource' import { useInvalidDataSourceList } from '@/service/use-pipeline' import { useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins' import UpdateSettingDialog from '../update-setting-dialog' import Card from './card' import InstallFromMarketplace from './install-from-marketplace' type DataSourcePageProps = { layout?: (parts: { body: ReactNode; toolbar: ReactNode }) => ReactNode onOpenMarketplace?: () => void stickyToolbar?: boolean } function DataSourceCardSkeleton() { return (
) } function DataSourceListSkeleton() { const { t } = useTranslation() return (
$.loading, { ns: 'common' })} className="space-y-2"> {Array.from({ length: 2 }, (_, index) => ( ))}
) } const DataSourcePage = ({ layout, onOpenMarketplace, stickyToolbar }: DataSourcePageProps) => { const { t } = useTranslation() const renderI18nObject = useRenderI18nObject() const [searchText, setSearchText] = useState('') const { canSetPluginPreferences } = usePluginSettingsAccess() const { data: enable_marketplace } = useSuspenseQuery({ ...systemFeaturesQueryOptions(), select: (s) => s.enable_marketplace, }) const { data, isLoading: isDataSourceListLoading } = useGetDataSourceListAuth() const { data: installedPluginList } = useInstalledPluginList() const pluginListWithLatestVersion = usePluginsWithLatestVersion(installedPluginList?.plugins) const invalidateInstalledPluginList = useInvalidateInstalledPluginList() const invalidateDataSourceListAuth = useInvalidDataSourceListAuth() const invalidateDataSourceList = useInvalidDataSourceList() const dataSources = useMemo(() => data?.result ?? [], [data?.result]) const dataSourcePluginDetails = useMemo(() => { return pluginListWithLatestVersion.filter( (plugin) => plugin.declaration.category === PluginCategoryEnum.datasource, ) }, [pluginListWithLatestVersion]) const filteredDataSources = useMemo(() => { const normalizedSearchText = searchText.trim().toLowerCase() if (!normalizedSearchText) return dataSources return dataSources.filter((item) => { const searchableText = [ item.name, item.provider, item.author, renderI18nObject(item.label), renderI18nObject(item.description), ] .join(' ') .toLowerCase() return searchableText.includes(normalizedSearchText) }) }, [dataSources, renderI18nObject, searchText]) const handlePluginUpdate = useCallback(() => { invalidateInstalledPluginList() invalidateDataSourceListAuth() invalidateDataSourceList() }, [invalidateDataSourceList, invalidateDataSourceListAuth, invalidateInstalledPluginList]) const toolbar = (
$['operation.search'], { ns: 'common' })} value={searchText} onValueChange={setSearchText} /> {canSetPluginPreferences && }
) const body = ( <> {isDataSourceListLoading && } {!isDataSourceListLoading && !dataSources.length && (
$['dataSourcePage.notSetUpTitle']} ns="common" components={{ highlight: , }} />
{t(($) => $['dataSourcePage.installFirst'], { ns: 'common' })}
)} {!isDataSourceListLoading && !!filteredDataSources.length && (
{filteredDataSources.map((item, index) => { const pluginDetail = dataSourcePluginDetails.find( (plugin) => plugin.plugin_id === item.plugin_id, ) return (
) })}
)} {!isDataSourceListLoading && enable_marketplace && ( )} ) if (layout) return
{layout({ body, toolbar })}
return (
{toolbar} {body}
) } export default memo(DataSourcePage)