mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-24 01:15:24 +08:00
feat(market): show certification badges in Core marketplace (#2615)
This commit is contained in:
@@ -298,6 +298,7 @@ function MarketPageContent({
|
||||
iconURL,
|
||||
githubURL: plugin.repository,
|
||||
version: plugin.latest_version,
|
||||
certificationStatus: plugin.certification_status,
|
||||
components: plugin.components || {},
|
||||
tags: plugin.tags || [],
|
||||
type: plugin.type,
|
||||
|
||||
@@ -57,6 +57,7 @@ function pluginToVO(
|
||||
iconURL,
|
||||
githubURL: plugin.repository,
|
||||
version: plugin.latest_version,
|
||||
certificationStatus: plugin.certification_status,
|
||||
components: plugin.components,
|
||||
tags: plugin.tags || [],
|
||||
type: plugin.type,
|
||||
|
||||
+4
@@ -1,3 +1,4 @@
|
||||
import { CertifiedPluginBadge } from '@/components/market/CertifiedPluginBadge';
|
||||
import { PluginMarketCardVO } from './PluginMarketCardVO';
|
||||
import { useRef, useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -276,6 +277,9 @@ export default function PluginMarketCardComponent({
|
||||
<span className="truncate">{typeLabel}</span>
|
||||
</Badge>
|
||||
)}
|
||||
{cardVO.certificationStatus === 'issued' && (
|
||||
<CertifiedPluginBadge compact />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
+3
@@ -9,6 +9,7 @@ export interface IPluginMarketCardVO {
|
||||
iconURL: string;
|
||||
githubURL: string;
|
||||
version: string;
|
||||
certificationStatus?: string;
|
||||
components?: Record<string, number>;
|
||||
tags?: string[];
|
||||
type?: 'plugin' | 'mcp' | 'skill';
|
||||
@@ -29,6 +30,7 @@ export class PluginMarketCardVO implements IPluginMarketCardVO {
|
||||
installCount: number;
|
||||
likeCount: number;
|
||||
version: string;
|
||||
certificationStatus?: string;
|
||||
components?: Record<string, number>;
|
||||
tags?: string[];
|
||||
type?: 'plugin' | 'mcp' | 'skill';
|
||||
@@ -46,6 +48,7 @@ export class PluginMarketCardVO implements IPluginMarketCardVO {
|
||||
this.likeCount = prop.likeCount ?? 0;
|
||||
this.pluginId = prop.pluginId;
|
||||
this.version = prop.version;
|
||||
this.certificationStatus = prop.certificationStatus;
|
||||
this.components = prop.components;
|
||||
this.tags = prop.tags;
|
||||
this.type = prop.type;
|
||||
|
||||
@@ -36,6 +36,7 @@ export enum PluginV4Status {
|
||||
}
|
||||
|
||||
export interface PluginV4 {
|
||||
certification_status?: string;
|
||||
id: number;
|
||||
plugin_id: string;
|
||||
mcp_id?: string;
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
'use client';
|
||||
|
||||
import { BadgeCheck } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip';
|
||||
|
||||
export function CertifiedPluginBadge({
|
||||
compact = false,
|
||||
}: {
|
||||
compact?: boolean;
|
||||
}) {
|
||||
const { t, i18n } = useTranslation();
|
||||
const language = i18n.language.startsWith('zh')
|
||||
? 'zh'
|
||||
: i18n.language.startsWith('ja')
|
||||
? 'ja'
|
||||
: 'en';
|
||||
const docsURL = `https://langbot.app/docs/${language}/plugin/certified-plugins`;
|
||||
return (
|
||||
<TooltipProvider delayDuration={200}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<a
|
||||
href={docsURL}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label={`${t('market.certifiedPlugin')}: ${t('market.certificationLearnMore')}`}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
className={`inline-flex shrink-0 items-center gap-1 rounded border border-emerald-600/25 bg-emerald-50 text-emerald-700 dark:bg-emerald-950/40 dark:text-emerald-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500 ${compact ? 'h-4 px-0.5' : 'px-2 py-0.5 text-xs font-medium'}`}
|
||||
>
|
||||
<BadgeCheck
|
||||
aria-hidden="true"
|
||||
className={compact ? 'h-3 w-3' : 'h-3.5 w-3.5'}
|
||||
/>
|
||||
{!compact && t('market.certifiedPlugin')}
|
||||
</a>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-72 text-xs">
|
||||
<p>{t('market.certificationTooltip')}</p>
|
||||
<a
|
||||
href={docsURL}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="mt-1 inline-block underline underline-offset-2"
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
{t('market.certificationLearnMore')}
|
||||
</a>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
);
|
||||
}
|
||||
@@ -1624,6 +1624,11 @@ const enUS = {
|
||||
},
|
||||
},
|
||||
market: {
|
||||
certifiedPlugin: 'Certified plugin',
|
||||
certificationTooltip:
|
||||
'This version has passed a review of data isolation and compatibility with shared runtimes, and its package is signed.',
|
||||
certificationLearnMore: 'Learn about certification',
|
||||
|
||||
runnerUsage: 'Runner usage',
|
||||
runnerUsageAll: 'All',
|
||||
runnerUsageAgent: 'Agent / Pipeline',
|
||||
|
||||
@@ -1655,6 +1655,11 @@ const esES = {
|
||||
},
|
||||
},
|
||||
market: {
|
||||
certifiedPlugin: 'Plugin certificado',
|
||||
certificationTooltip:
|
||||
'Esta versión ha superado la revisión de aislamiento de datos y compatibilidad con entornos compartidos. El paquete está firmado.',
|
||||
certificationLearnMore: 'Acerca de la certificación',
|
||||
|
||||
runnerUsage: 'Uso del ejecutor',
|
||||
runnerUsageAll: 'Todos',
|
||||
runnerUsageAgent: 'Agent / Flujo',
|
||||
|
||||
@@ -1639,6 +1639,11 @@ const jaJP = {
|
||||
},
|
||||
},
|
||||
market: {
|
||||
certifiedPlugin: '認証済みプラグイン',
|
||||
certificationTooltip:
|
||||
'このバージョンはデータ分離と共有実行環境との互換性の審査に合格し、パッケージに署名されています。',
|
||||
certificationLearnMore: 'プラグイン認証について',
|
||||
|
||||
runnerUsage: 'ランナーの用途',
|
||||
runnerUsageAll: 'すべて',
|
||||
runnerUsageAgent: 'Agent / パイプライン',
|
||||
|
||||
@@ -1651,6 +1651,11 @@ const ruRU = {
|
||||
},
|
||||
},
|
||||
market: {
|
||||
certifiedPlugin: 'Сертифицированный плагин',
|
||||
certificationTooltip:
|
||||
'Эта версия прошла проверку изоляции данных и совместимости с общей средой выполнения. Пакет подписан.',
|
||||
certificationLearnMore: 'О сертификации',
|
||||
|
||||
runnerUsage: 'Назначение исполнителя',
|
||||
runnerUsageAll: 'Все',
|
||||
runnerUsageAgent: 'Agent / Конвейер',
|
||||
|
||||
@@ -1593,6 +1593,11 @@ const thTH = {
|
||||
},
|
||||
},
|
||||
market: {
|
||||
certifiedPlugin: 'ปลั๊กอินที่ผ่านการรับรอง',
|
||||
certificationTooltip:
|
||||
'เวอร์ชันนี้ผ่านการตรวจสอบการแยกข้อมูลและความเข้ากันได้กับสภาพแวดล้อมรันร่วมกัน และแพ็กเกจได้รับการลงนามแล้ว',
|
||||
certificationLearnMore: 'เกี่ยวกับการรับรองปลั๊กอิน',
|
||||
|
||||
runnerUsage: 'การใช้งานรันเนอร์',
|
||||
runnerUsageAll: 'ทั้งหมด',
|
||||
runnerUsageAgent: 'Agent / ไปป์ไลน์',
|
||||
|
||||
@@ -1619,6 +1619,11 @@ const viVN = {
|
||||
},
|
||||
},
|
||||
market: {
|
||||
certifiedPlugin: 'Plugin được chứng nhận',
|
||||
certificationTooltip:
|
||||
'Phiên bản này đã vượt qua đánh giá về cách ly dữ liệu và khả năng tương thích với môi trường chạy dùng chung. Gói đã được ký.',
|
||||
certificationLearnMore: 'Tìm hiểu về chứng nhận',
|
||||
|
||||
runnerUsage: 'Mục đích trình chạy',
|
||||
runnerUsageAll: 'Tất cả',
|
||||
runnerUsageAgent: 'Agent / Pipeline',
|
||||
|
||||
@@ -1531,6 +1531,11 @@ const zhHans = {
|
||||
},
|
||||
},
|
||||
market: {
|
||||
certifiedPlugin: '认证插件',
|
||||
certificationTooltip:
|
||||
'此版本已通过数据隔离与共享运行环境兼容性审核,插件包已签名。',
|
||||
certificationLearnMore: '了解插件认证',
|
||||
|
||||
runnerUsage: '运行器用途',
|
||||
runnerUsageAll: '全部',
|
||||
runnerUsageAgent: 'Agent / 流水线',
|
||||
|
||||
@@ -1529,6 +1529,11 @@ const zhHant = {
|
||||
},
|
||||
},
|
||||
market: {
|
||||
certifiedPlugin: '認證外掛',
|
||||
certificationTooltip:
|
||||
'此版本已通過資料隔離與共享執行環境相容性審核,外掛套件已簽章。',
|
||||
certificationLearnMore: '瞭解外掛認證',
|
||||
|
||||
runnerUsage: '運行器用途',
|
||||
runnerUsageAll: '全部',
|
||||
runnerUsageAgent: 'Agent / 流水線',
|
||||
|
||||
Reference in New Issue
Block a user