'use client' import type { FC } from 'react' import type { ActivePluginType } from '../../marketplace/constants' import { cn } from '@langgenius/dify-ui/cn' import { Popover, PopoverContent, PopoverTrigger, } from '@langgenius/dify-ui/popover' import * as React from 'react' import { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import Loading from '@/app/components/base/loading' import SearchBox from '@/app/components/plugins/marketplace/search-box' import { useInstalledPluginList } from '@/service/use-plugins' import { PLUGIN_TYPE_SEARCH_MAP } from '../../marketplace/constants' import { PluginSource } from '../../types' import NoDataPlaceholder from './no-data-placeholder' import ToolItem from './tool-item' type Props = { trigger: React.ReactNode value: string[] onChange: (value: string[]) => void isShow: boolean onShowChange: (isShow: boolean) => void } const ToolPicker: FC = ({ trigger, value, onChange, isShow, onShowChange, }) => { const { t } = useTranslation() const tabs = [ { key: PLUGIN_TYPE_SEARCH_MAP.all, name: t('category.all', { ns: 'plugin' }) }, { key: PLUGIN_TYPE_SEARCH_MAP.model, name: t('category.models', { ns: 'plugin' }) }, { key: PLUGIN_TYPE_SEARCH_MAP.tool, name: t('category.tools', { ns: 'plugin' }) }, { key: PLUGIN_TYPE_SEARCH_MAP.agent, name: t('category.agents', { ns: 'plugin' }) }, { key: PLUGIN_TYPE_SEARCH_MAP.extension, name: t('category.extensions', { ns: 'plugin' }) }, { key: PLUGIN_TYPE_SEARCH_MAP.datasource, name: t('category.datasources', { ns: 'plugin' }) }, { key: PLUGIN_TYPE_SEARCH_MAP.trigger, name: t('category.triggers', { ns: 'plugin' }) }, { key: PLUGIN_TYPE_SEARCH_MAP.bundle, name: t('category.bundles', { ns: 'plugin' }) }, ] const [pluginType, setPluginType] = useState(PLUGIN_TYPE_SEARCH_MAP.all) const [query, setQuery] = useState('') const [tags, setTags] = useState([]) const { data, isLoading } = useInstalledPluginList() const filteredList = useMemo(() => { const list = data ? data.plugins : [] return list.filter((plugin) => { const isFromMarketPlace = plugin.source === PluginSource.marketplace return ( isFromMarketPlace && (pluginType === PLUGIN_TYPE_SEARCH_MAP.all || plugin.declaration.category === pluginType) && (tags.length === 0 || tags.some(tag => plugin.declaration.tags.includes(tag))) && (query === '' || plugin.plugin_id.toLowerCase().includes(query.toLowerCase())) ) }) }, [data, pluginType, query, tags]) const handleCheckChange = (pluginId: string) => { const newValue = value.includes(pluginId) ? value.filter(id => id !== pluginId) : [...value, pluginId] onChange(newValue) } const listContent = (
{filteredList.map(item => ( handleCheckChange(item.plugin_id)} /> ))}
) const loadingContent = (
) const noData = ( ) const resolvedTrigger = React.isValidElement(trigger) ? trigger :
{trigger}
return (
{tabs.map(tab => (
setPluginType(tab.key)} > {tab.name}
))}
{!isLoading && filteredList.length > 0 && listContent} {!isLoading && filteredList.length === 0 && noData} {isLoading && loadingContent}
) } export default React.memo(ToolPicker)