mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 12:37:20 +08:00
use plugin detail for builtin tool
This commit is contained in:
parent
f213c8f393
commit
78c867b9a3
@ -6,26 +6,23 @@ import EndpointList from './endpoint-list'
|
|||||||
import ActionList from './action-list'
|
import ActionList from './action-list'
|
||||||
import ModelList from './model-list'
|
import ModelList from './model-list'
|
||||||
import Drawer from '@/app/components/base/drawer'
|
import Drawer from '@/app/components/base/drawer'
|
||||||
import { usePluginPageContext } from '@/app/components/plugins/plugin-page/context'
|
|
||||||
import type { PluginDetail } from '@/app/components/plugins/types'
|
import type { PluginDetail } from '@/app/components/plugins/types'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
detail?: PluginDetail
|
detail?: PluginDetail
|
||||||
onUpdate: () => void
|
onUpdate: () => void
|
||||||
|
onHide: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const PluginDetailPanel: FC<Props> = ({
|
const PluginDetailPanel: FC<Props> = ({
|
||||||
detail,
|
detail,
|
||||||
onUpdate,
|
onUpdate,
|
||||||
|
onHide,
|
||||||
}) => {
|
}) => {
|
||||||
const setCurrentPluginID = usePluginPageContext(v => v.setCurrentPluginID)
|
|
||||||
|
|
||||||
const handleHide = () => setCurrentPluginID(undefined)
|
|
||||||
|
|
||||||
const handleUpdate = (isDelete = false) => {
|
const handleUpdate = (isDelete = false) => {
|
||||||
if (isDelete)
|
if (isDelete)
|
||||||
handleHide()
|
onHide()
|
||||||
onUpdate()
|
onUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +33,7 @@ const PluginDetailPanel: FC<Props> = ({
|
|||||||
<Drawer
|
<Drawer
|
||||||
isOpen={!!detail}
|
isOpen={!!detail}
|
||||||
clickOutsideNotOpen={false}
|
clickOutsideNotOpen={false}
|
||||||
onClose={handleHide}
|
onClose={onHide}
|
||||||
footer={null}
|
footer={null}
|
||||||
mask={false}
|
mask={false}
|
||||||
positionCenter={false}
|
positionCenter={false}
|
||||||
@ -46,7 +43,7 @@ const PluginDetailPanel: FC<Props> = ({
|
|||||||
<>
|
<>
|
||||||
<DetailHeader
|
<DetailHeader
|
||||||
detail={detail}
|
detail={detail}
|
||||||
onHide={handleHide}
|
onHide={onHide}
|
||||||
onUpdate={handleUpdate}
|
onUpdate={handleUpdate}
|
||||||
/>
|
/>
|
||||||
<div className='grow overflow-y-auto'>
|
<div className='grow overflow-y-auto'>
|
||||||
|
|||||||
@ -15,6 +15,7 @@ const PluginsPanel = () => {
|
|||||||
const { data: pluginList, isLoading: isPluginListLoading } = useInstalledPluginList()
|
const { data: pluginList, isLoading: isPluginListLoading } = useInstalledPluginList()
|
||||||
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
||||||
const currentPluginID = usePluginPageContext(v => v.currentPluginID)
|
const currentPluginID = usePluginPageContext(v => v.currentPluginID)
|
||||||
|
const setCurrentPluginID = usePluginPageContext(v => v.setCurrentPluginID)
|
||||||
|
|
||||||
const { run: handleFilterChange } = useDebounceFn((filters: FilterState) => {
|
const { run: handleFilterChange } = useDebounceFn((filters: FilterState) => {
|
||||||
setFilters(filters)
|
setFilters(filters)
|
||||||
@ -37,6 +38,8 @@ const PluginsPanel = () => {
|
|||||||
return detail
|
return detail
|
||||||
}, [currentPluginID, pluginList?.plugins])
|
}, [currentPluginID, pluginList?.plugins])
|
||||||
|
|
||||||
|
const handleHide = () => setCurrentPluginID(undefined)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='flex flex-col pt-1 pb-3 px-12 justify-center items-start gap-3 self-stretch'>
|
<div className='flex flex-col pt-1 pb-3 px-12 justify-center items-start gap-3 self-stretch'>
|
||||||
@ -54,7 +57,11 @@ const PluginsPanel = () => {
|
|||||||
) : (
|
) : (
|
||||||
<Empty />
|
<Empty />
|
||||||
)}
|
)}
|
||||||
<PluginDetailPanel detail={currentPluginDetail} onUpdate={() => invalidateInstalledPluginList()}/>
|
<PluginDetailPanel
|
||||||
|
detail={currentPluginDetail}
|
||||||
|
onUpdate={() => invalidateInstalledPluginList()}
|
||||||
|
onHide={handleHide}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,8 +14,10 @@ import CustomCreateCard from '@/app/components/tools/provider/custom-create-card
|
|||||||
import WorkflowToolEmpty from '@/app/components/tools/add-tool-modal/empty'
|
import WorkflowToolEmpty from '@/app/components/tools/add-tool-modal/empty'
|
||||||
import Card from '@/app/components/plugins/card'
|
import Card from '@/app/components/plugins/card'
|
||||||
import CardMoreInfo from '@/app/components/plugins/card/card-more-info'
|
import CardMoreInfo from '@/app/components/plugins/card/card-more-info'
|
||||||
|
import PluginDetailPanel from '@/app/components/plugins/plugin-detail-panel'
|
||||||
import { useSelector as useAppContextSelector } from '@/context/app-context'
|
import { useSelector as useAppContextSelector } from '@/context/app-context'
|
||||||
import { useAllToolProviders } from '@/service/use-tools'
|
import { useAllToolProviders } from '@/service/use-tools'
|
||||||
|
import { useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||||
|
|
||||||
const ProviderList = () => {
|
const ProviderList = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@ -52,92 +54,105 @@ const ProviderList = () => {
|
|||||||
}, [activeTab, tagFilterValue, keywords, collectionList])
|
}, [activeTab, tagFilterValue, keywords, collectionList])
|
||||||
|
|
||||||
const [currentProvider, setCurrentProvider] = useState<Collection | undefined>()
|
const [currentProvider, setCurrentProvider] = useState<Collection | undefined>()
|
||||||
|
const { data: pluginList } = useInstalledPluginList()
|
||||||
|
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
||||||
|
const currentPluginDetail = useMemo(() => {
|
||||||
|
const detail = pluginList?.plugins.find(plugin => plugin.plugin_id === currentProvider?.plugin_id)
|
||||||
|
return detail
|
||||||
|
}, [currentProvider?.plugin_id, pluginList?.plugins])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative flex overflow-hidden bg-gray-100 shrink-0 h-0 grow'>
|
<>
|
||||||
<div
|
<div className='relative flex overflow-hidden bg-gray-100 shrink-0 h-0 grow'>
|
||||||
ref={containerRef}
|
<div
|
||||||
className='relative flex flex-col overflow-y-auto bg-gray-100 grow'
|
ref={containerRef}
|
||||||
>
|
className='relative flex flex-col overflow-y-auto bg-gray-100 grow'
|
||||||
<div className={cn(
|
>
|
||||||
'sticky top-0 flex justify-between items-center pt-4 px-12 pb-2 leading-[56px] bg-gray-100 z-20 flex-wrap gap-y-2',
|
|
||||||
currentProvider && 'pr-6',
|
|
||||||
)}>
|
|
||||||
<TabSliderNew
|
|
||||||
value={activeTab}
|
|
||||||
onChange={(state) => {
|
|
||||||
setActiveTab(state)
|
|
||||||
if (state !== activeTab)
|
|
||||||
setCurrentProvider(undefined)
|
|
||||||
}}
|
|
||||||
options={options}
|
|
||||||
/>
|
|
||||||
<div className='flex items-center gap-2'>
|
|
||||||
<LabelFilter value={tagFilterValue} onChange={handleTagsChange} />
|
|
||||||
<Input
|
|
||||||
showLeftIcon
|
|
||||||
showClearIcon
|
|
||||||
wrapperClassName='w-[200px]'
|
|
||||||
value={keywords}
|
|
||||||
onChange={e => handleKeywordsChange(e.target.value)}
|
|
||||||
onClear={() => handleKeywordsChange('')}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{(filteredCollectionList.length > 0 || activeTab !== 'builtin') && (
|
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
'relative grid content-start grid-cols-1 gap-4 px-12 pt-2 pb-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 grow shrink-0',
|
'sticky top-0 flex justify-between items-center pt-4 px-12 pb-2 leading-[56px] bg-gray-100 z-20 flex-wrap gap-y-2',
|
||||||
|
currentProvider && 'pr-6',
|
||||||
)}>
|
)}>
|
||||||
{activeTab === 'api' && <CustomCreateCard onRefreshData={refetch} />}
|
<TabSliderNew
|
||||||
{filteredCollectionList.map(collection => (
|
value={activeTab}
|
||||||
<div
|
onChange={(state) => {
|
||||||
key={collection.id}
|
setActiveTab(state)
|
||||||
onClick={() => setCurrentProvider(collection)}
|
if (state !== activeTab)
|
||||||
>
|
setCurrentProvider(undefined)
|
||||||
<Card
|
|
||||||
className={cn(
|
|
||||||
'border-[1.5px] border-transparent cursor-pointer',
|
|
||||||
currentProvider?.id === collection.id && 'border-components-option-card-option-selected-border',
|
|
||||||
)}
|
|
||||||
hideCornerMark
|
|
||||||
payload={{
|
|
||||||
...collection,
|
|
||||||
brief: collection.description,
|
|
||||||
} as any}
|
|
||||||
footer={
|
|
||||||
<CardMoreInfo
|
|
||||||
tags={collection.labels}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{!filteredCollectionList.length && activeTab === 'workflow' && <div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'><WorkflowToolEmpty /></div>}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!filteredCollectionList.length && activeTab === 'builtin' && (
|
|
||||||
<Empty lightCard text={t('tools.noTools')} className='px-12' />
|
|
||||||
)}
|
|
||||||
{
|
|
||||||
enable_marketplace && activeTab === 'builtin' && (
|
|
||||||
<Marketplace
|
|
||||||
onMarketplaceScroll={() => {
|
|
||||||
containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'smooth' })
|
|
||||||
}}
|
}}
|
||||||
searchPluginText={keywords}
|
options={options}
|
||||||
filterPluginTags={tagFilterValue}
|
|
||||||
/>
|
/>
|
||||||
)
|
<div className='flex items-center gap-2'>
|
||||||
}
|
<LabelFilter value={tagFilterValue} onChange={handleTagsChange} />
|
||||||
|
<Input
|
||||||
|
showLeftIcon
|
||||||
|
showClearIcon
|
||||||
|
wrapperClassName='w-[200px]'
|
||||||
|
value={keywords}
|
||||||
|
onChange={e => handleKeywordsChange(e.target.value)}
|
||||||
|
onClear={() => handleKeywordsChange('')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{(filteredCollectionList.length > 0 || activeTab !== 'builtin') && (
|
||||||
|
<div className={cn(
|
||||||
|
'relative grid content-start grid-cols-1 gap-4 px-12 pt-2 pb-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 grow shrink-0',
|
||||||
|
)}>
|
||||||
|
{activeTab === 'api' && <CustomCreateCard onRefreshData={refetch} />}
|
||||||
|
{filteredCollectionList.map(collection => (
|
||||||
|
<div
|
||||||
|
key={collection.id}
|
||||||
|
onClick={() => setCurrentProvider(collection)}
|
||||||
|
>
|
||||||
|
<Card
|
||||||
|
className={cn(
|
||||||
|
'border-[1.5px] border-transparent cursor-pointer',
|
||||||
|
currentProvider?.id === collection.id && 'border-components-option-card-option-selected-border',
|
||||||
|
)}
|
||||||
|
hideCornerMark
|
||||||
|
payload={{
|
||||||
|
...collection,
|
||||||
|
brief: collection.description,
|
||||||
|
} as any}
|
||||||
|
footer={
|
||||||
|
<CardMoreInfo
|
||||||
|
tags={collection.labels}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{!filteredCollectionList.length && activeTab === 'workflow' && <div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'><WorkflowToolEmpty /></div>}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!filteredCollectionList.length && activeTab === 'builtin' && (
|
||||||
|
<Empty lightCard text={t('tools.noTools')} className='px-12' />
|
||||||
|
)}
|
||||||
|
{
|
||||||
|
enable_marketplace && activeTab === 'builtin' && (
|
||||||
|
<Marketplace
|
||||||
|
onMarketplaceScroll={() => {
|
||||||
|
containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'smooth' })
|
||||||
|
}}
|
||||||
|
searchPluginText={keywords}
|
||||||
|
filterPluginTags={tagFilterValue}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{currentProvider && (
|
{currentProvider && !currentProvider.plugin_id && (
|
||||||
<ProviderDetail
|
<ProviderDetail
|
||||||
collection={currentProvider}
|
collection={currentProvider}
|
||||||
onHide={() => setCurrentProvider(undefined)}
|
onHide={() => setCurrentProvider(undefined)}
|
||||||
onRefreshData={refetch}
|
onRefreshData={refetch}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
<PluginDetailPanel
|
||||||
|
detail={currentPluginDetail}
|
||||||
|
onUpdate={() => invalidateInstalledPluginList()}
|
||||||
|
onHide={() => setCurrentProvider(undefined)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ProviderList.displayName = 'ToolProviderList'
|
ProviderList.displayName = 'ToolProviderList'
|
||||||
|
|||||||
@ -48,6 +48,7 @@ export type Collection = {
|
|||||||
is_team_authorization: boolean
|
is_team_authorization: boolean
|
||||||
allow_delete: boolean
|
allow_delete: boolean
|
||||||
labels: string[]
|
labels: string[]
|
||||||
|
plugin_id?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ToolParameter = {
|
export type ToolParameter = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user