diff --git a/web/app/components/header/account-setting/data-source-page-new/card.tsx b/web/app/components/header/account-setting/data-source-page-new/card.tsx index 08b8bbb7bb..6d0e0bc688 100644 --- a/web/app/components/header/account-setting/data-source-page-new/card.tsx +++ b/web/app/components/header/account-setting/data-source-page-new/card.tsx @@ -6,7 +6,7 @@ const Card = () => { return (
-
+
Notion Data Source diff --git a/web/app/components/header/account-setting/data-source-page-new/hooks.ts b/web/app/components/header/account-setting/data-source-page-new/hooks.ts new file mode 100644 index 0000000000..b4369eb400 --- /dev/null +++ b/web/app/components/header/account-setting/data-source-page-new/hooks.ts @@ -0,0 +1,80 @@ +import { + useCallback, + useEffect, + useMemo, + useState, +} from 'react' +import { + useMarketplacePlugins, +} from '@/app/components/plugins/marketplace/hooks' +import type { Plugin } from '@/app/components/plugins/types' +import { PluginType } from '@/app/components/plugins/types' +import { getMarketplacePluginsByCollectionId } from '@/app/components/plugins/marketplace/utils' + +export const useMarketplaceAllPlugins = (providers: any[], searchText: string) => { + const exclude = useMemo(() => { + return providers.map(provider => provider.provider.replace(/(.+)\/([^/]+)$/, '$1')) + }, [providers]) + const [collectionPlugins, setCollectionPlugins] = useState([]) + + const { + plugins, + queryPlugins, + queryPluginsWithDebounced, + isLoading, + } = useMarketplacePlugins() + + const getCollectionPlugins = useCallback(async () => { + const collectionPlugins = await getMarketplacePluginsByCollectionId('__model-settings-pinned-models') + + setCollectionPlugins(collectionPlugins) + }, []) + + useEffect(() => { + getCollectionPlugins() + }, [getCollectionPlugins]) + + useEffect(() => { + if (searchText) { + queryPluginsWithDebounced({ + query: searchText, + category: PluginType.datasource, + exclude, + type: 'plugin', + sortBy: 'install_count', + sortOrder: 'DESC', + }) + } + else { + queryPlugins({ + query: '', + category: PluginType.datasource, + type: 'plugin', + pageSize: 1000, + exclude, + sortBy: 'install_count', + sortOrder: 'DESC', + }) + } + }, [queryPlugins, queryPluginsWithDebounced, searchText, exclude]) + + const allPlugins = useMemo(() => { + const allPlugins = [...collectionPlugins.filter(plugin => !exclude.includes(plugin.plugin_id))] + + if (plugins?.length) { + for (let i = 0; i < plugins.length; i++) { + const plugin = plugins[i] + + if (plugin.type !== 'bundle' && !allPlugins.find(p => p.plugin_id === plugin.plugin_id)) + allPlugins.push(plugin) + } + } + + return allPlugins + }, [plugins, collectionPlugins, exclude]) + + return { + plugins: allPlugins, + isLoading, + } +} diff --git a/web/app/components/header/account-setting/data-source-page-new/index.tsx b/web/app/components/header/account-setting/data-source-page-new/index.tsx index 108267fa51..6e1c140e93 100644 --- a/web/app/components/header/account-setting/data-source-page-new/index.tsx +++ b/web/app/components/header/account-setting/data-source-page-new/index.tsx @@ -1,12 +1,26 @@ +import { memo } from 'react' import Card from './card' +import InstallFromMarketplace from './install-from-marketplace' +import { useGlobalPublicStore } from '@/context/global-public-context' const DataSourcePage = () => { + const { enable_marketplace } = useGlobalPublicStore(s => s.systemFeatures) return ( -
- - +
+
+ + +
+ { + enable_marketplace && ( + + ) + }
) } -export default DataSourcePage +export default memo(DataSourcePage) diff --git a/web/app/components/header/account-setting/data-source-page-new/install-from-marketplace.tsx b/web/app/components/header/account-setting/data-source-page-new/install-from-marketplace.tsx new file mode 100644 index 0000000000..da3738d0f2 --- /dev/null +++ b/web/app/components/header/account-setting/data-source-page-new/install-from-marketplace.tsx @@ -0,0 +1,80 @@ +import { useCallback, useState } from 'react' +import { useTheme } from 'next-themes' +import { useTranslation } from 'react-i18next' +import Link from 'next/link' +import { + RiArrowDownSLine, + RiArrowRightUpLine, +} from '@remixicon/react' +import { + useMarketplaceAllPlugins, +} from './hooks' +import Divider from '@/app/components/base/divider' +import Loading from '@/app/components/base/loading' +import ProviderCard from '@/app/components/plugins/provider-card' +import List from '@/app/components/plugins/marketplace/list' +import type { Plugin } from '@/app/components/plugins/types' +import cn from '@/utils/classnames' +import { getLocaleOnClient } from '@/i18n' +import { getMarketplaceUrl } from '@/utils/var' + +type InstallFromMarketplaceProps = { + providers: any[] + searchText: string +} +const InstallFromMarketplace = ({ + providers, + searchText, +}: InstallFromMarketplaceProps) => { + const { t } = useTranslation() + const { theme } = useTheme() + const [collapse, setCollapse] = useState(false) + const locale = getLocaleOnClient() + const { + plugins: allPlugins, + isLoading: isAllPluginsLoading, + } = useMarketplaceAllPlugins(providers, searchText) + + const cardRender = useCallback((plugin: Plugin) => { + if (plugin.type === 'bundle') + return null + + return + }, []) + + return ( +
+ +
+
setCollapse(!collapse)}> + + {t('common.modelProvider.installProvider')} +
+
+ {t('common.modelProvider.discoverMore')} + + {t('plugin.marketplace.difyMarketplace')} + + +
+
+ {!collapse && isAllPluginsLoading && } + { + !isAllPluginsLoading && !collapse && ( + + ) + } +
+ ) +} + +export default InstallFromMarketplace