feat: partner badge in marketplace (#14258)
This commit is contained in:
37
web/app/components/plugins/base/badges/icon-with-tooltip.tsx
Normal file
37
web/app/components/plugins/base/badges/icon-with-tooltip.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React, { type FC } from 'react'
|
||||
import cn from '@/utils/classnames'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Theme } from '@/types/app'
|
||||
|
||||
type IconWithTooltipProps = {
|
||||
className?: string
|
||||
popupContent?: string
|
||||
theme: Theme
|
||||
BadgeIconLight: React.ElementType
|
||||
BadgeIconDark: React.ElementType
|
||||
}
|
||||
|
||||
const IconWithTooltip: FC<IconWithTooltipProps> = ({
|
||||
className,
|
||||
theme,
|
||||
popupContent,
|
||||
BadgeIconLight,
|
||||
BadgeIconDark,
|
||||
}) => {
|
||||
const isDark = theme === Theme.dark
|
||||
const iconClassName = cn('w-5 h-5', className)
|
||||
const Icon = isDark ? BadgeIconDark : BadgeIconLight
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
popupClassName='p-1.5 border-[0.5px] border-[0.5px] border-components-panel-border bg-components-tooltip-bg text-text-secondary system-xs-medium'
|
||||
popupContent={popupContent}
|
||||
>
|
||||
<div className='flex items-center justify-center shrink-0'>
|
||||
<Icon className={iconClassName} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(IconWithTooltip)
|
29
web/app/components/plugins/base/badges/partner.tsx
Normal file
29
web/app/components/plugins/base/badges/partner.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import IconWithTooltip from './icon-with-tooltip'
|
||||
import PartnerDark from '@/app/components/base/icons/src/public/plugins/PartnerDark'
|
||||
import PartnerLight from '@/app/components/base/icons/src/public/plugins/PartnerLight'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
|
||||
type PartnerProps = {
|
||||
className?: string
|
||||
}
|
||||
|
||||
const Partner: FC<PartnerProps> = ({
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { theme } = useTheme()
|
||||
|
||||
return (
|
||||
<IconWithTooltip
|
||||
className={className}
|
||||
theme={theme}
|
||||
BadgeIconLight={PartnerLight}
|
||||
BadgeIconDark={PartnerDark}
|
||||
popupContent={t('plugin.marketplace.partnerTip')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Partner
|
29
web/app/components/plugins/base/badges/verified.tsx
Normal file
29
web/app/components/plugins/base/badges/verified.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import IconWithTooltip from './icon-with-tooltip'
|
||||
import VerifiedDark from '@/app/components/base/icons/src/public/plugins/VerifiedDark'
|
||||
import VerifiedLight from '@/app/components/base/icons/src/public/plugins/VerifiedLight'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
|
||||
type VerifiedProps = {
|
||||
className?: string
|
||||
}
|
||||
|
||||
const Verified: FC<VerifiedProps> = ({
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { theme } = useTheme()
|
||||
|
||||
return (
|
||||
<IconWithTooltip
|
||||
className={className}
|
||||
theme={theme}
|
||||
BadgeIconLight={VerifiedLight}
|
||||
BadgeIconDark={VerifiedDark}
|
||||
popupContent={t('plugin.marketplace.verifiedTip')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Verified
|
@@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { RiVerifiedBadgeLine } from '@remixicon/react'
|
||||
import type { Plugin } from '../types'
|
||||
import Icon from '../card/base/card-icon'
|
||||
import CornerMark from './base/corner-mark'
|
||||
@@ -14,6 +13,8 @@ import { getLanguage } from '@/i18n/language'
|
||||
import { useSingleCategories } from '../hooks'
|
||||
import { renderI18nObject } from '@/hooks/use-i18n'
|
||||
import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks'
|
||||
import Partner from '../base/badges/partner'
|
||||
import Verified from '../base/badges/verified'
|
||||
|
||||
export type Props = {
|
||||
className?: string
|
||||
@@ -46,11 +47,12 @@ const Card = ({
|
||||
const locale = localeFromProps ? getLanguage(localeFromProps) : defaultLocale
|
||||
const { t } = useMixedTranslation(localeFromProps)
|
||||
const { categoriesMap } = useSingleCategories(t)
|
||||
const { category, type, name, org, label, brief, icon, verified } = payload
|
||||
const { category, type, name, org, label, brief, icon, verified, badges = [] } = payload
|
||||
const isBundle = !['plugin', 'model', 'tool', 'extension', 'agent-strategy'].includes(type)
|
||||
const cornerMark = isBundle ? categoriesMap.bundle?.label : categoriesMap[category]?.label
|
||||
const getLocalizedText = (obj: Record<string, string> | undefined) =>
|
||||
obj ? renderI18nObject(obj, locale) : ''
|
||||
const isPartner = badges.includes('partner')
|
||||
|
||||
const wrapClassName = cn('relative p-4 pb-3 border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg hover-bg-components-panel-on-panel-item-bg rounded-xl shadow-xs', className)
|
||||
if (isLoading) {
|
||||
@@ -71,7 +73,8 @@ const Card = ({
|
||||
<div className="ml-3 w-0 grow">
|
||||
<div className="flex items-center h-5">
|
||||
<Title title={getLocalizedText(label)} />
|
||||
{verified && <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" />}
|
||||
{isPartner && <Partner className='w-4 h-4 ml-0.5' />}
|
||||
{verified && <Verified className='w-4 h-4 ml-0.5' />}
|
||||
{titleLeft} {/* This can be version badge */}
|
||||
</div>
|
||||
<OrgInfo
|
||||
|
@@ -38,7 +38,7 @@ export const pluginManifestInMarketToPluginProps = (pluginManifest: PluginManife
|
||||
label: pluginManifest.label,
|
||||
brief: pluginManifest.brief,
|
||||
icon: pluginManifest.icon,
|
||||
verified: pluginManifest.verified,
|
||||
verified: true,
|
||||
introduction: pluginManifest.introduction,
|
||||
repository: '',
|
||||
install_count: 0,
|
||||
@@ -46,6 +46,7 @@ export const pluginManifestInMarketToPluginProps = (pluginManifest: PluginManife
|
||||
settings: [],
|
||||
},
|
||||
tags: [],
|
||||
badges: pluginManifest.badges,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -87,6 +87,7 @@ export type PluginManifestInMarket = {
|
||||
introduction: string
|
||||
verified: boolean
|
||||
install_count: number
|
||||
badges: string[]
|
||||
}
|
||||
|
||||
export type PluginDetail = {
|
||||
@@ -137,6 +138,7 @@ export type Plugin = {
|
||||
settings: CredentialFormSchemaBase[]
|
||||
}
|
||||
tags: { name: string }[]
|
||||
badges: string[]
|
||||
}
|
||||
|
||||
export enum PermissionType {
|
||||
|
Reference in New Issue
Block a user