mirror of
https://github.com/langgenius/dify.git
synced 2026-07-21 18:58:35 +08:00
fix: not support jump to detail in marketplace (#39347)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
8d406aec31
commit
4f8477427e
@ -122,6 +122,22 @@ describe('getPluginLinkInMarketplace', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('getPluginDetailLinkInMarketplace', () => {
|
||||
it('should return the local detail link for a regular plugin', async () => {
|
||||
const { getPluginDetailLinkInMarketplace } = await import('../utils')
|
||||
const plugin = createMockPlugin({ org: 'test-org', name: 'test-plugin', type: 'plugin' })
|
||||
|
||||
expect(getPluginDetailLinkInMarketplace(plugin)).toBe('/plugin/test-org/test-plugin')
|
||||
})
|
||||
|
||||
it('should return the local detail link for a bundle', async () => {
|
||||
const { getPluginDetailLinkInMarketplace } = await import('../utils')
|
||||
const bundle = createMockPlugin({ org: 'test-org', name: 'test-bundle', type: 'bundle' })
|
||||
|
||||
expect(getPluginDetailLinkInMarketplace(bundle)).toBe('/bundles/test-org/test-bundle')
|
||||
})
|
||||
})
|
||||
|
||||
describe('getMarketplaceListCondition', () => {
|
||||
it('should return category condition for tool', async () => {
|
||||
const { getMarketplaceListCondition } = await import('../utils')
|
||||
|
||||
@ -8,6 +8,7 @@ import StickySearchAndSwitchWrapper from './sticky-search-and-switch-wrapper'
|
||||
|
||||
type MarketplaceProps = {
|
||||
showInstallButton?: boolean
|
||||
linkToMarketplaceDetail?: boolean
|
||||
pluginTypeSwitchClassName?: string
|
||||
isMarketplacePlatform?: boolean
|
||||
marketplaceNav?: React.ReactNode
|
||||
@ -19,6 +20,7 @@ type MarketplaceProps = {
|
||||
|
||||
const Marketplace = async ({
|
||||
showInstallButton = false,
|
||||
linkToMarketplaceDetail = false,
|
||||
pluginTypeSwitchClassName,
|
||||
isMarketplacePlatform = false,
|
||||
marketplaceNav,
|
||||
@ -35,7 +37,10 @@ const Marketplace = async ({
|
||||
{!isMarketplacePlatform && (
|
||||
<StickySearchAndSwitchWrapper pluginTypeSwitchClassName={pluginTypeSwitchClassName} />
|
||||
)}
|
||||
<ListWrapper showInstallButton={showInstallButton} />
|
||||
<ListWrapper
|
||||
showInstallButton={showInstallButton}
|
||||
linkToMarketplaceDetail={linkToMarketplaceDetail}
|
||||
/>
|
||||
</PluginInstallPermissionProviderGuard>
|
||||
</HydrateQueryClient>
|
||||
</TanstackQueryInitializer>
|
||||
|
||||
@ -87,13 +87,19 @@ describe('CardWrapper', () => {
|
||||
</ThemeProvider>,
|
||||
)
|
||||
|
||||
it('renders a non-navigating card when install button is hidden', () => {
|
||||
it('renders a non-navigating card by default when install button is hidden', () => {
|
||||
renderCardWrapper()
|
||||
|
||||
expect(screen.queryByRole('link')).not.toBeInTheDocument()
|
||||
expect(screen.getByTestId('card-more-info')).toHaveTextContent('42:tag:search|tag:agent')
|
||||
})
|
||||
|
||||
it('links the card to its marketplace detail when explicitly enabled', () => {
|
||||
renderCardWrapper({ linkToMarketplaceDetail: true })
|
||||
|
||||
expect(screen.getByRole('link')).toHaveAttribute('href', '/detail/dify/plugin-a')
|
||||
})
|
||||
|
||||
it('renders install and marketplace detail actions when install button is shown', () => {
|
||||
renderCardWrapper({ showInstallButton: true })
|
||||
|
||||
|
||||
@ -11,17 +11,20 @@ import CardMoreInfo from '@/app/components/plugins/card/card-more-info'
|
||||
import { useTags } from '@/app/components/plugins/hooks'
|
||||
import { useOptionalPluginInstallPermission } from '@/app/components/plugins/install-plugin/hooks/use-plugin-install-permission'
|
||||
import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace'
|
||||
import { getPluginLinkInMarketplace } from '../utils'
|
||||
import Link from '@/next/link'
|
||||
import { getPluginDetailLinkInMarketplace, getPluginLinkInMarketplace } from '../utils'
|
||||
|
||||
type CardWrapperProps = {
|
||||
plugin: Plugin
|
||||
showInstallButton?: boolean
|
||||
isInstalled?: boolean
|
||||
linkToMarketplaceDetail?: boolean
|
||||
}
|
||||
const CardWrapperComponent = ({
|
||||
plugin,
|
||||
showInstallButton,
|
||||
isInstalled = false,
|
||||
linkToMarketplaceDetail = false,
|
||||
}: CardWrapperProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { theme } = useTheme()
|
||||
@ -102,7 +105,7 @@ const CardWrapperComponent = ({
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
const card = (
|
||||
<div className="group relative rounded-xl">
|
||||
<Card
|
||||
key={plugin.name}
|
||||
@ -118,6 +121,17 @@ const CardWrapperComponent = ({
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
if (!linkToMarketplaceDetail) return card
|
||||
|
||||
return (
|
||||
<Link
|
||||
href={getPluginDetailLinkInMarketplace(plugin)}
|
||||
className="block rounded-xl focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden"
|
||||
>
|
||||
{card}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
// Memoize the component to prevent unnecessary re-renders when props haven't changed
|
||||
|
||||
@ -15,6 +15,7 @@ type ListProps = {
|
||||
marketplaceCollectionPluginsMap: Record<string, Plugin[]>
|
||||
plugins?: Plugin[]
|
||||
showInstallButton?: boolean
|
||||
linkToMarketplaceDetail?: boolean
|
||||
cardContainerClassName?: string
|
||||
cardRender?: (plugin: Plugin) => React.JSX.Element | null
|
||||
emptyClassName?: string
|
||||
@ -25,6 +26,7 @@ const List = ({
|
||||
marketplaceCollectionPluginsMap,
|
||||
plugins,
|
||||
showInstallButton,
|
||||
linkToMarketplaceDetail,
|
||||
cardContainerClassName,
|
||||
cardRender,
|
||||
emptyClassName,
|
||||
@ -62,6 +64,7 @@ const List = ({
|
||||
marketplaceCollections={marketplaceCollections}
|
||||
marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap}
|
||||
showInstallButton={showInstallButton}
|
||||
linkToMarketplaceDetail={linkToMarketplaceDetail}
|
||||
cardContainerClassName={cardContainerClassName}
|
||||
cardRender={cardRender}
|
||||
onCollectionMoreClick={onCollectionMoreClick}
|
||||
@ -79,6 +82,7 @@ const List = ({
|
||||
plugin={plugin}
|
||||
showInstallButton={showInstallButton}
|
||||
isInstalled={installedPluginIds.has(plugin.plugin_id)}
|
||||
linkToMarketplaceDetail={linkToMarketplaceDetail}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
|
||||
@ -35,6 +35,7 @@ type ListWithCollectionProps = {
|
||||
marketplaceCollections: MarketplaceCollection[]
|
||||
marketplaceCollectionPluginsMap: Record<string, Plugin[]>
|
||||
showInstallButton?: boolean
|
||||
linkToMarketplaceDetail?: boolean
|
||||
cardContainerClassName?: string
|
||||
cardRender?: (plugin: Plugin) => React.JSX.Element | null
|
||||
onCollectionMoreClick?: (searchParams?: SearchParamsFromCollection) => void
|
||||
@ -46,13 +47,25 @@ type PluginCardProps = {
|
||||
showInstallButton?: boolean
|
||||
cardRender?: (plugin: Plugin) => React.JSX.Element | null
|
||||
isInstalled?: boolean
|
||||
linkToMarketplaceDetail?: boolean
|
||||
}
|
||||
|
||||
const PluginCard = ({ plugin, showInstallButton, cardRender, isInstalled }: PluginCardProps) => {
|
||||
const PluginCard = ({
|
||||
plugin,
|
||||
showInstallButton,
|
||||
cardRender,
|
||||
isInstalled,
|
||||
linkToMarketplaceDetail,
|
||||
}: PluginCardProps) => {
|
||||
if (cardRender) return cardRender(plugin)
|
||||
|
||||
return (
|
||||
<CardWrapper plugin={plugin} showInstallButton={showInstallButton} isInstalled={isInstalled} />
|
||||
<CardWrapper
|
||||
plugin={plugin}
|
||||
showInstallButton={showInstallButton}
|
||||
isInstalled={isInstalled}
|
||||
linkToMarketplaceDetail={linkToMarketplaceDetail}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@ -60,6 +73,7 @@ const ListWithCollection = ({
|
||||
marketplaceCollections,
|
||||
marketplaceCollectionPluginsMap,
|
||||
showInstallButton,
|
||||
linkToMarketplaceDetail,
|
||||
cardContainerClassName,
|
||||
cardRender,
|
||||
onCollectionMoreClick,
|
||||
@ -147,6 +161,7 @@ const ListWithCollection = ({
|
||||
<PluginCard
|
||||
plugin={plugin}
|
||||
showInstallButton={showInstallButton}
|
||||
linkToMarketplaceDetail={linkToMarketplaceDetail}
|
||||
cardRender={cardRender}
|
||||
isInstalled={installedPluginIds?.has(plugin.plugin_id)}
|
||||
/>
|
||||
@ -163,6 +178,7 @@ const ListWithCollection = ({
|
||||
key={plugin.plugin_id}
|
||||
plugin={plugin}
|
||||
showInstallButton={showInstallButton}
|
||||
linkToMarketplaceDetail={linkToMarketplaceDetail}
|
||||
cardRender={cardRender}
|
||||
isInstalled={installedPluginIds?.has(plugin.plugin_id)}
|
||||
/>
|
||||
|
||||
@ -7,8 +7,9 @@ import List from './index'
|
||||
|
||||
type ListWrapperProps = {
|
||||
showInstallButton?: boolean
|
||||
linkToMarketplaceDetail?: boolean
|
||||
}
|
||||
const ListWrapper = ({ showInstallButton }: ListWrapperProps) => {
|
||||
const ListWrapper = ({ showInstallButton, linkToMarketplaceDetail }: ListWrapperProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const {
|
||||
@ -45,6 +46,7 @@ const ListWrapper = ({ showInstallButton }: ListWrapperProps) => {
|
||||
marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap || {}}
|
||||
plugins={plugins}
|
||||
showInstallButton={showInstallButton}
|
||||
linkToMarketplaceDetail={linkToMarketplaceDetail}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -60,6 +60,16 @@ export const getPluginLinkInMarketplace = (
|
||||
return getMarketplaceUrl(`/plugins/${plugin.org}/${plugin.name}`, params)
|
||||
}
|
||||
|
||||
export const getPluginDetailLinkInMarketplace = (
|
||||
plugin: Pick<MarketplacePluginPayload, 'name' | 'org' | 'type'>,
|
||||
) => {
|
||||
const org = encodeURIComponent(plugin.org)
|
||||
const name = encodeURIComponent(plugin.name)
|
||||
|
||||
if (plugin.type === 'bundle') return `/bundles/${org}/${name}`
|
||||
return `/plugin/${org}/${name}`
|
||||
}
|
||||
|
||||
export const getMarketplaceCategoryUrl = (
|
||||
category?: string,
|
||||
params?: Record<string, string | undefined>,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user