diff --git a/web/app/components/plugins/card/index.tsx b/web/app/components/plugins/card/index.tsx index b262727506..2d66e1b872 100644 --- a/web/app/components/plugins/card/index.tsx +++ b/web/app/components/plugins/card/index.tsx @@ -11,6 +11,7 @@ import Placeholder from './base/placeholder' import cn from '@/utils/classnames' import { useGetLanguage } from '@/context/i18n' import { getLanguage } from '@/i18n/language' +import { useCategories } from '../hooks' export type Props = { className?: string @@ -41,9 +42,9 @@ const Card = ({ }: Props) => { const defaultLocale = useGetLanguage() const locale = localeFromProps ? getLanguage(localeFromProps) : defaultLocale - - const { type, name, org, label, brief, icon, verified } = payload - + const { categoriesMap } = useCategories() + const { type, category, name, org, label, brief, icon, verified } = payload + const cornerMark = type !== 'plugin' ? type : categoriesMap[category].label const getLocalizedText = (obj: Record | undefined) => obj?.[locale] || obj?.['en-US'] || obj?.en_US || '' @@ -59,7 +60,7 @@ const Card = ({ return (
- {!hideCornerMark && } + {!hideCornerMark && } {/* Header */}
diff --git a/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx b/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx index 553c30f6be..44b63cf7dd 100644 --- a/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx +++ b/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useState } from 'react' import Modal from '@/app/components/base/modal' -import type { Plugin, PluginManifestInMarket } from '../../types' +import type { Dependency, Plugin, PluginManifestInMarket } from '../../types' import { InstallStep, PluginType } from '../../types' import Install from './steps/install' import Installed from '../base/installed' @@ -10,12 +10,15 @@ import { useTranslation } from 'react-i18next' import { useUpdateModelProviders } from '@/app/components/header/account-setting/model-provider-page/hooks' import { useInvalidateInstalledPluginList } from '@/service/use-plugins' import { useInvalidateAllToolProviders } from '@/service/use-tools' +import ReadyToInstallBundle from '../install-bundle/ready-to-install' const i18nPrefix = 'plugin.installModal' type InstallFromMarketplaceProps = { uniqueIdentifier: string manifest: PluginManifestInMarket | Plugin + isBundle?: boolean + dependencies?: Dependency[] onSuccess: () => void onClose: () => void } @@ -23,6 +26,8 @@ type InstallFromMarketplaceProps = { const InstallFromMarketplace: React.FC = ({ uniqueIdentifier, manifest, + isBundle, + dependencies, onSuccess, onClose, }) => { @@ -83,7 +88,14 @@ const InstallFromMarketplace: React.FC = ({ ) } { - ([InstallStep.installed, InstallStep.installFailed].includes(step)) && ( + isBundle ? ( + + ) : ([InstallStep.installed, InstallStep.installFailed].includes(step)) && ( {verified && }
{isFromGitHub ? meta!.version : version}
- {isFromMarketplace && hasNewVersion && } + {isFromMarketplace && } } hasRedCornerMark={hasNewVersion} diff --git a/web/app/components/plugins/plugin-detail-panel/index.tsx b/web/app/components/plugins/plugin-detail-panel/index.tsx index c9e4213137..d42304742b 100644 --- a/web/app/components/plugins/plugin-detail-panel/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/index.tsx @@ -6,26 +6,23 @@ import EndpointList from './endpoint-list' import ActionList from './action-list' import ModelList from './model-list' 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 cn from '@/utils/classnames' type Props = { detail?: PluginDetail onUpdate: () => void + onHide: () => void } const PluginDetailPanel: FC = ({ detail, onUpdate, + onHide, }) => { - const setCurrentPluginID = usePluginPageContext(v => v.setCurrentPluginID) - - const handleHide = () => setCurrentPluginID(undefined) - const handleUpdate = (isDelete = false) => { if (isDelete) - handleHide() + onHide() onUpdate() } @@ -36,7 +33,7 @@ const PluginDetailPanel: FC = ({ = ({ <>
diff --git a/web/app/components/plugins/plugin-page/plugins-panel.tsx b/web/app/components/plugins/plugin-page/plugins-panel.tsx index 49153bbb53..76e3ea7eca 100644 --- a/web/app/components/plugins/plugin-page/plugins-panel.tsx +++ b/web/app/components/plugins/plugin-page/plugins-panel.tsx @@ -15,6 +15,7 @@ const PluginsPanel = () => { const { data: pluginList, isLoading: isPluginListLoading } = useInstalledPluginList() const invalidateInstalledPluginList = useInvalidateInstalledPluginList() const currentPluginID = usePluginPageContext(v => v.currentPluginID) + const setCurrentPluginID = usePluginPageContext(v => v.setCurrentPluginID) const { run: handleFilterChange } = useDebounceFn((filters: FilterState) => { setFilters(filters) @@ -37,6 +38,8 @@ const PluginsPanel = () => { return detail }, [currentPluginID, pluginList?.plugins]) + const handleHide = () => setCurrentPluginID(undefined) + return ( <>
@@ -54,7 +57,11 @@ const PluginsPanel = () => { ) : ( )} - invalidateInstalledPluginList()}/> + invalidateInstalledPluginList()} + onHide={handleHide} + /> ) } diff --git a/web/app/components/plugins/types.ts b/web/app/components/plugins/types.ts index 4bf4f54c66..b300b6b6e4 100644 --- a/web/app/components/plugins/types.ts +++ b/web/app/components/plugins/types.ts @@ -107,7 +107,7 @@ export type PluginDetail = { } export type Plugin = { - type: PluginType + type: 'plugin' | 'bundle' org: string name: string plugin_id: string diff --git a/web/app/components/tools/provider-list.tsx b/web/app/components/tools/provider-list.tsx index 863d4ed5f7..a6f5accec2 100644 --- a/web/app/components/tools/provider-list.tsx +++ b/web/app/components/tools/provider-list.tsx @@ -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 Card from '@/app/components/plugins/card' 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 { useAllToolProviders } from '@/service/use-tools' +import { useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins' const ProviderList = () => { const { t } = useTranslation() @@ -52,92 +54,105 @@ const ProviderList = () => { }, [activeTab, tagFilterValue, keywords, collectionList]) const [currentProvider, setCurrentProvider] = useState() + 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 ( -
-
-
- { - setActiveTab(state) - if (state !== activeTab) - setCurrentProvider(undefined) - }} - options={options} - /> -
- - handleKeywordsChange(e.target.value)} - onClear={() => handleKeywordsChange('')} - /> -
-
- {(filteredCollectionList.length > 0 || activeTab !== 'builtin') && ( + <> +
+
- {activeTab === 'api' && } - {filteredCollectionList.map(collection => ( -
setCurrentProvider(collection)} - > - - } - /> -
- ))} - {!filteredCollectionList.length && activeTab === 'workflow' &&
} -
- )} - {!filteredCollectionList.length && activeTab === 'builtin' && ( - - )} - { - enable_marketplace && activeTab === 'builtin' && ( - { - containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'smooth' }) + { + setActiveTab(state) + if (state !== activeTab) + setCurrentProvider(undefined) }} - searchPluginText={keywords} - filterPluginTags={tagFilterValue} + options={options} /> - ) - } +
+ + handleKeywordsChange(e.target.value)} + onClear={() => handleKeywordsChange('')} + /> +
+
+ {(filteredCollectionList.length > 0 || activeTab !== 'builtin') && ( +
+ {activeTab === 'api' && } + {filteredCollectionList.map(collection => ( +
setCurrentProvider(collection)} + > + + } + /> +
+ ))} + {!filteredCollectionList.length && activeTab === 'workflow' &&
} +
+ )} + {!filteredCollectionList.length && activeTab === 'builtin' && ( + + )} + { + enable_marketplace && activeTab === 'builtin' && ( + { + containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'smooth' }) + }} + searchPluginText={keywords} + filterPluginTags={tagFilterValue} + /> + ) + } +
- {currentProvider && ( + {currentProvider && !currentProvider.plugin_id && ( setCurrentProvider(undefined)} onRefreshData={refetch} /> )} -
+ invalidateInstalledPluginList()} + onHide={() => setCurrentProvider(undefined)} + /> + ) } ProviderList.displayName = 'ToolProviderList' diff --git a/web/app/components/tools/types.ts b/web/app/components/tools/types.ts index 34cc491481..27f187d1f7 100644 --- a/web/app/components/tools/types.ts +++ b/web/app/components/tools/types.ts @@ -48,6 +48,7 @@ export type Collection = { is_team_authorization: boolean allow_delete: boolean labels: string[] + plugin_id?: string } export type ToolParameter = {