mirror of
https://github.com/langgenius/dify.git
synced 2026-05-04 01:18:05 +08:00
feat: enhance model plugin workflow checks and model provider management UX (#33289)
Signed-off-by: yyh <yuanyouhuilyz@gmail.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: CodingOnStar <hanxujiang@dify.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Coding On Star <447357187@qq.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: -LAN- <laipz8200@outlook.com> Co-authored-by: statxc <tyleradams93226@gmail.com>
This commit is contained in:
@ -2,6 +2,7 @@ import type { Plugin } from '../../types'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import * as React from 'react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { API_PREFIX, MARKETPLACE_API_PREFIX } from '@/config'
|
||||
import { PluginCategoryEnum } from '../../types'
|
||||
import Card from '../index'
|
||||
|
||||
@ -40,6 +41,12 @@ vi.mock('@/utils/format', () => ({
|
||||
formatNumber: (num: number) => num.toLocaleString(),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/app-context', () => ({
|
||||
useSelector: (selector: (value: { currentWorkspace: { id: string } }) => string) => selector({
|
||||
currentWorkspace: { id: 'workspace-123' },
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/utils/mcp', () => ({
|
||||
shouldUseMcpIcon: (src: unknown) => typeof src === 'object' && src !== null && (src as { content?: string })?.content === '🔗',
|
||||
}))
|
||||
@ -189,6 +196,36 @@ describe('Card', () => {
|
||||
expect(iconElement).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should normalize package icon filenames to workspace icon urls', () => {
|
||||
const plugin = createMockPlugin({
|
||||
from: 'package',
|
||||
icon: 'custom-icon.png',
|
||||
})
|
||||
|
||||
const { container } = render(<Card payload={plugin} />)
|
||||
|
||||
const iconElement = container.querySelector('[style*="background-image"]')
|
||||
expect(iconElement).toBeInTheDocument()
|
||||
expect(iconElement).toHaveStyle({
|
||||
backgroundImage: `url(${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=workspace-123&filename=custom-icon.png)`,
|
||||
})
|
||||
})
|
||||
|
||||
it('should normalize marketplace icon filenames to marketplace icon urls', () => {
|
||||
const plugin = createMockPlugin({
|
||||
from: 'marketplace',
|
||||
icon: 'custom-icon.png',
|
||||
})
|
||||
|
||||
const { container } = render(<Card payload={plugin} />)
|
||||
|
||||
const iconElement = container.querySelector('[style*="background-image"]')
|
||||
expect(iconElement).toBeInTheDocument()
|
||||
expect(iconElement).toHaveStyle({
|
||||
backgroundImage: `url(${MARKETPLACE_API_PREFIX}/plugins/${plugin.org}/${plugin.name}/icon)`,
|
||||
})
|
||||
})
|
||||
|
||||
it('should use icon_dark when theme is dark and icon_dark is provided', () => {
|
||||
// Set theme to dark
|
||||
mockTheme = 'dark'
|
||||
|
||||
@ -3,6 +3,7 @@ import type { Plugin } from '../types'
|
||||
import { useTranslation } from '#i18n'
|
||||
import { RiAlertFill } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useSelector } from '@/context/app-context'
|
||||
import { useGetLanguage } from '@/context/i18n'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
import {
|
||||
@ -14,6 +15,7 @@ import Partner from '../base/badges/partner'
|
||||
import Verified from '../base/badges/verified'
|
||||
import Icon from '../card/base/card-icon'
|
||||
import { useCategories } from '../hooks'
|
||||
import { getPluginCardIconUrl } from '../utils'
|
||||
import CornerMark from './base/corner-mark'
|
||||
import Description from './base/description'
|
||||
import OrgInfo from './base/org-info'
|
||||
@ -50,9 +52,14 @@ const Card = ({
|
||||
const locale = useGetLanguage()
|
||||
const { t } = useTranslation()
|
||||
const { categoriesMap } = useCategories(true)
|
||||
const { category, type, name, org, label, brief, icon, icon_dark, verified, badges = [] } = payload
|
||||
const currentWorkspaceId = useSelector(s => s.currentWorkspace.id)
|
||||
const { category, type, name, org, label, brief, icon, icon_dark, verified, badges = [], from } = payload
|
||||
const { theme } = useTheme()
|
||||
const iconSrc = theme === Theme.dark && icon_dark ? icon_dark : icon
|
||||
const iconSrc = getPluginCardIconUrl(
|
||||
{ from, name, org, type },
|
||||
theme === Theme.dark && icon_dark ? icon_dark : icon,
|
||||
currentWorkspaceId,
|
||||
)
|
||||
const getLocalizedText = (obj: Record<string, string> | undefined) =>
|
||||
obj ? renderI18nObject(obj, locale) : ''
|
||||
const isPartner = badges.includes('partner')
|
||||
@ -101,7 +108,7 @@ const Card = ({
|
||||
&& (
|
||||
<div className="relative flex h-8 items-center gap-x-2 px-3 after:absolute after:bottom-0 after:left-0 after:right-0 after:top-0 after:bg-toast-warning-bg after:opacity-40">
|
||||
<RiAlertFill className="h-3 w-3 shrink-0 text-text-warning-secondary" />
|
||||
<p className="system-xs-regular z-10 grow text-text-secondary">
|
||||
<p className="z-10 grow text-text-secondary system-xs-regular">
|
||||
{t('installModal.installWarning', { ns: 'plugin' })}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user