Merge branch 'feat/plugins' into dev/plugin-deploy

This commit is contained in:
StyleZhang 2024-12-03 14:35:36 +08:00
commit 66b79ee323
12 changed files with 78 additions and 19 deletions

View File

@ -264,6 +264,7 @@ export const useMarketplace = (providers: ModelProvider[], searchText: string) =
query: searchText, query: searchText,
category: PluginType.model, category: PluginType.model,
exclude, exclude,
type: 'plugin',
}) })
} }
else { else {
@ -271,6 +272,7 @@ export const useMarketplace = (providers: ModelProvider[], searchText: string) =
category: PluginType.model, category: PluginType.model,
condition: getMarketplaceListCondition(PluginType.model), condition: getMarketplaceListCondition(PluginType.model),
exclude, exclude,
type: 'plugin',
}) })
resetPlugins() resetPlugins()
} }

View File

@ -44,7 +44,7 @@ const Card = ({
const locale = localeFromProps ? getLanguage(localeFromProps) : defaultLocale const locale = localeFromProps ? getLanguage(localeFromProps) : defaultLocale
const { categoriesMap } = useCategories() const { categoriesMap } = useCategories()
const { type, category, name, org, label, brief, icon, verified } = payload const { type, category, name, org, label, brief, icon, verified } = payload
const cornerMark = type !== 'plugin' ? type : categoriesMap[category]?.label const cornerMark = type !== 'plugin' ? categoriesMap.bundle?.label : categoriesMap[category]?.label
const getLocalizedText = (obj: Record<string, string> | undefined) => const getLocalizedText = (obj: Record<string, string> | undefined) =>
obj?.[locale] || obj?.['en-US'] || obj?.en_US || '' obj?.[locale] || obj?.['en-US'] || obj?.en_US || ''

View File

@ -30,7 +30,10 @@ import {
useMarketplaceCollectionsAndPlugins, useMarketplaceCollectionsAndPlugins,
useMarketplacePlugins, useMarketplacePlugins,
} from './hooks' } from './hooks'
import { getMarketplaceListCondition } from './utils' import {
getMarketplaceListCondition,
getMarketplaceListFilterType,
} from './utils'
import { useInstalledPluginList } from '@/service/use-plugins' import { useInstalledPluginList } from '@/service/use-plugins'
export type MarketplaceContextValue = { export type MarketplaceContextValue = {
@ -60,7 +63,7 @@ export const MarketplaceContext = createContext<MarketplaceContextValue>({
handleSearchPluginTextChange: () => {}, handleSearchPluginTextChange: () => {},
filterPluginTags: [], filterPluginTags: [],
handleFilterPluginTagsChange: () => {}, handleFilterPluginTagsChange: () => {},
activePluginType: PLUGIN_TYPE_SEARCH_MAP.all, activePluginType: 'all',
handleActivePluginTypeChange: () => {}, handleActivePluginTypeChange: () => {},
plugins: undefined, plugins: undefined,
resetPlugins: () => {}, resetPlugins: () => {},
@ -131,6 +134,7 @@ export const MarketplaceContextProvider = ({
tags: hasValidTags ? tagsFromSearchParams : [], tags: hasValidTags ? tagsFromSearchParams : [],
sortBy: sortRef.current.sortBy, sortBy: sortRef.current.sortBy,
sortOrder: sortRef.current.sortOrder, sortOrder: sortRef.current.sortOrder,
type: getMarketplaceListFilterType(activePluginTypeRef.current),
}) })
history.pushState({}, '', `/${searchParams?.language ? `?language=${searchParams?.language}` : ''}`) history.pushState({}, '', `/${searchParams?.language ? `?language=${searchParams?.language}` : ''}`)
} }
@ -138,6 +142,7 @@ export const MarketplaceContextProvider = ({
if (shouldExclude && isSuccess) { if (shouldExclude && isSuccess) {
queryMarketplaceCollectionsAndPlugins({ queryMarketplaceCollectionsAndPlugins({
exclude, exclude,
type: getMarketplaceListFilterType(activePluginTypeRef.current),
}) })
} }
} }
@ -153,6 +158,7 @@ export const MarketplaceContextProvider = ({
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current, category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
condition: getMarketplaceListCondition(activePluginTypeRef.current), condition: getMarketplaceListCondition(activePluginTypeRef.current),
exclude, exclude,
type: getMarketplaceListFilterType(activePluginTypeRef.current),
}) })
resetPlugins() resetPlugins()
@ -178,6 +184,7 @@ export const MarketplaceContextProvider = ({
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current, category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
condition: getMarketplaceListCondition(activePluginTypeRef.current), condition: getMarketplaceListCondition(activePluginTypeRef.current),
exclude, exclude,
type: getMarketplaceListFilterType(activePluginTypeRef.current),
}) })
resetPlugins() resetPlugins()
@ -191,6 +198,7 @@ export const MarketplaceContextProvider = ({
sortBy: sortRef.current.sortBy, sortBy: sortRef.current.sortBy,
sortOrder: sortRef.current.sortOrder, sortOrder: sortRef.current.sortOrder,
exclude, exclude,
type: getMarketplaceListFilterType(activePluginTypeRef.current),
}) })
}, [queryPlugins, resetPlugins, queryMarketplaceCollectionsAndPlugins, exclude]) }, [queryPlugins, resetPlugins, queryMarketplaceCollectionsAndPlugins, exclude])
@ -203,6 +211,7 @@ export const MarketplaceContextProvider = ({
category: type === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : type, category: type === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : type,
condition: getMarketplaceListCondition(type), condition: getMarketplaceListCondition(type),
exclude, exclude,
type: getMarketplaceListFilterType(activePluginTypeRef.current),
}) })
resetPlugins() resetPlugins()
@ -216,6 +225,7 @@ export const MarketplaceContextProvider = ({
sortBy: sortRef.current.sortBy, sortBy: sortRef.current.sortBy,
sortOrder: sortRef.current.sortOrder, sortOrder: sortRef.current.sortOrder,
exclude, exclude,
type: getMarketplaceListFilterType(activePluginTypeRef.current),
}) })
}, [queryPlugins, resetPlugins, queryMarketplaceCollectionsAndPlugins, exclude]) }, [queryPlugins, resetPlugins, queryMarketplaceCollectionsAndPlugins, exclude])
@ -230,6 +240,7 @@ export const MarketplaceContextProvider = ({
sortBy: sortRef.current.sortBy, sortBy: sortRef.current.sortBy,
sortOrder: sortRef.current.sortOrder, sortOrder: sortRef.current.sortOrder,
exclude, exclude,
type: getMarketplaceListFilterType(activePluginTypeRef.current),
}) })
}, [queryPlugins, exclude]) }, [queryPlugins, exclude])

View File

@ -13,8 +13,8 @@ import type {
PluginsSearchParams, PluginsSearchParams,
} from './types' } from './types'
import { import {
getFormattedPlugin,
getMarketplaceCollectionsAndPlugins, getMarketplaceCollectionsAndPlugins,
getPluginIconInMarketplace,
} from './utils' } from './utils'
import i18n from '@/i18n/i18next-config' import i18n from '@/i18n/i18next-config'
import { import {
@ -64,10 +64,9 @@ export const useMarketplacePlugins = () => {
}) })
return { return {
plugins: data?.data?.plugins.map(plugin => ({ plugins: data?.data?.plugins.map((plugin) => {
...plugin, return getFormattedPlugin(plugin)
icon: getPluginIconInMarketplace(plugin), }),
})),
resetPlugins: reset, resetPlugins: reset,
queryPlugins, queryPlugins,
queryPluginsWithDebounced, queryPluginsWithDebounced,

View File

@ -1,9 +1,9 @@
'use client' 'use client'
import { RiArrowRightUpLine } from '@remixicon/react' import { RiArrowRightUpLine } from '@remixicon/react'
import { getPluginLinkInMarketplace } from '../utils'
import Card from '@/app/components/plugins/card' import Card from '@/app/components/plugins/card'
import CardMoreInfo from '@/app/components/plugins/card/card-more-info' import CardMoreInfo from '@/app/components/plugins/card/card-more-info'
import type { Plugin } from '@/app/components/plugins/types' import type { Plugin } from '@/app/components/plugins/types'
import { MARKETPLACE_URL_PREFIX } from '@/config'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks' import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks'
import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace' import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace'
@ -55,7 +55,7 @@ const CardWrapper = ({
> >
{t('plugin.detailPanel.operation.install')} {t('plugin.detailPanel.operation.install')}
</Button> </Button>
<a href={`${MARKETPLACE_URL_PREFIX}/plugins/${plugin.org}/${plugin.name}?language=${localeFromLocale}`} target='_blank' className='block flex-1 shrink-0 w-[calc(50%-4px)]'> <a href={`${getPluginLinkInMarketplace(plugin)}?language=${localeFromLocale}`} target='_blank' className='block flex-1 shrink-0 w-[calc(50%-4px)]'>
<Button <Button
className='w-full gap-0.5' className='w-full gap-0.5'
> >
@ -83,7 +83,7 @@ const CardWrapper = ({
return ( return (
<a <a
className='group inline-block relative rounded-xl cursor-pointer' className='group inline-block relative rounded-xl cursor-pointer'
href={`${MARKETPLACE_URL_PREFIX}/plugins/${plugin.org}/${plugin.name}`} href={getPluginLinkInMarketplace(plugin)}
> >
<Card <Card
key={plugin.name} key={plugin.name}

View File

@ -28,6 +28,7 @@ export type PluginsSearchParams = {
category?: string category?: string
tags?: string[] tags?: string[]
exclude?: string[] exclude?: string[]
type?: 'plugin' | 'bundle'
} }
export type PluginsSort = { export type PluginsSort = {
@ -39,6 +40,7 @@ export type CollectionsAndPluginsSearchParams = {
category?: string category?: string
condition?: string condition?: string
exclude?: string[] exclude?: string[]
type?: 'plugin' | 'bundle'
} }
export type SearchParams = { export type SearchParams = {

View File

@ -1,15 +1,42 @@
import { PLUGIN_TYPE_SEARCH_MAP } from './plugin-type-switch'
import type { Plugin } from '@/app/components/plugins/types' import type { Plugin } from '@/app/components/plugins/types'
import { PluginType } from '@/app/components/plugins/types' import { PluginType } from '@/app/components/plugins/types'
import type { import type {
CollectionsAndPluginsSearchParams, CollectionsAndPluginsSearchParams,
MarketplaceCollection, MarketplaceCollection,
} from '@/app/components/plugins/marketplace/types' } from '@/app/components/plugins/marketplace/types'
import { MARKETPLACE_API_PREFIX } from '@/config' import {
MARKETPLACE_API_PREFIX,
MARKETPLACE_URL_PREFIX,
} from '@/config'
export const getPluginIconInMarketplace = (plugin: Plugin) => { export const getPluginIconInMarketplace = (plugin: Plugin) => {
if (plugin.type === 'bundle')
return `${MARKETPLACE_API_PREFIX}/bundles/${plugin.org}/${plugin.name}/icon`
return `${MARKETPLACE_API_PREFIX}/plugins/${plugin.org}/${plugin.name}/icon` return `${MARKETPLACE_API_PREFIX}/plugins/${plugin.org}/${plugin.name}/icon`
} }
export const getFormattedPlugin = (bundle: any) => {
if (bundle.type === 'bundle') {
return {
...bundle,
icon: getPluginIconInMarketplace(bundle),
brief: bundle.description,
label: bundle.labels,
}
}
return {
...bundle,
icon: getPluginIconInMarketplace(bundle),
}
}
export const getPluginLinkInMarketplace = (plugin: Plugin) => {
if (plugin.type === 'bundle')
return `${MARKETPLACE_URL_PREFIX}/bundles/${plugin.org}/${plugin.name}`
return `${MARKETPLACE_URL_PREFIX}/plugins/${plugin.org}/${plugin.name}`
}
export const getMarketplaceCollectionsAndPlugins = async (query?: CollectionsAndPluginsSearchParams) => { export const getMarketplaceCollectionsAndPlugins = async (query?: CollectionsAndPluginsSearchParams) => {
let marketplaceCollections = [] as MarketplaceCollection[] let marketplaceCollections = [] as MarketplaceCollection[]
let marketplaceCollectionPluginsMap = {} as Record<string, Plugin[]> let marketplaceCollectionPluginsMap = {} as Record<string, Plugin[]>
@ -17,6 +44,8 @@ export const getMarketplaceCollectionsAndPlugins = async (query?: CollectionsAnd
let marketplaceUrl = `${MARKETPLACE_API_PREFIX}/collections?page=1&page_size=100` let marketplaceUrl = `${MARKETPLACE_API_PREFIX}/collections?page=1&page_size=100`
if (query?.condition) if (query?.condition)
marketplaceUrl += `&condition=${query.condition}` marketplaceUrl += `&condition=${query.condition}`
if (query?.type)
marketplaceUrl += `&type=${query.type}`
const marketplaceCollectionsData = await globalThis.fetch(marketplaceUrl, { cache: 'no-store' }) const marketplaceCollectionsData = await globalThis.fetch(marketplaceUrl, { cache: 'no-store' })
const marketplaceCollectionsDataJson = await marketplaceCollectionsData.json() const marketplaceCollectionsDataJson = await marketplaceCollectionsData.json()
marketplaceCollections = marketplaceCollectionsDataJson.data.collections marketplaceCollections = marketplaceCollectionsDataJson.data.collections
@ -30,15 +59,13 @@ export const getMarketplaceCollectionsAndPlugins = async (query?: CollectionsAnd
body: JSON.stringify({ body: JSON.stringify({
category: query?.category, category: query?.category,
exclude: query?.exclude, exclude: query?.exclude,
type: query?.type,
}), }),
}, },
) )
const marketplaceCollectionPluginsDataJson = await marketplaceCollectionPluginsData.json() const marketplaceCollectionPluginsDataJson = await marketplaceCollectionPluginsData.json()
const plugins = marketplaceCollectionPluginsDataJson.data.plugins.map((plugin: Plugin) => { const plugins = marketplaceCollectionPluginsDataJson.data.plugins.map((plugin: Plugin) => {
return { return getFormattedPlugin(plugin)
...plugin,
icon: getPluginIconInMarketplace(plugin),
}
}) })
marketplaceCollectionPluginsMap[collection.name] = plugins marketplaceCollectionPluginsMap[collection.name] = plugins
@ -68,3 +95,13 @@ export const getMarketplaceListCondition = (pluginType: string) => {
return '' return ''
} }
export const getMarketplaceListFilterType = (category: string) => {
if (category === PLUGIN_TYPE_SEARCH_MAP.all)
return undefined
if (category === PLUGIN_TYPE_SEARCH_MAP.bundle)
return 'bundle'
return 'plugin'
}

View File

@ -11,10 +11,11 @@ import Title from './card/base/title'
import DownloadCount from './card/base/download-count' import DownloadCount from './card/base/download-count'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { useGetLanguage } from '@/context/i18n' import { useGetLanguage } from '@/context/i18n'
import { MARKETPLACE_URL_PREFIX } from '@/config'
import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace' import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { useBoolean } from 'ahooks' import { useBoolean } from 'ahooks'
import { getPluginLinkInMarketplace } from '@/app/components/plugins/marketplace/utils'
import { useI18N } from '@/context/i18n'
type Props = { type Props = {
className?: string className?: string
@ -32,6 +33,7 @@ const ProviderCard: FC<Props> = ({
}] = useBoolean(false) }] = useBoolean(false)
const language = useGetLanguage() const language = useGetLanguage()
const { org, label } = payload const { org, label } = payload
const { locale } = useI18N()
return ( return (
<div className={cn('group 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)}> <div className={cn('group 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)}>
@ -72,7 +74,7 @@ const ProviderCard: FC<Props> = ({
className='grow' className='grow'
variant='secondary' variant='secondary'
> >
<a href={`${MARKETPLACE_URL_PREFIX}/plugins/${payload.org}/${payload.name}`} target='_blank' className='flex items-center gap-0.5'> <a href={`${getPluginLinkInMarketplace(payload)}?language=${locale}`} target='_blank' className='flex items-center gap-0.5'>
{t('plugin.detailPanel.operation.detail')} {t('plugin.detailPanel.operation.detail')}
<RiArrowRightUpLine className='w-4 h-4' /> <RiArrowRightUpLine className='w-4 h-4' />
</a> </a>

View File

@ -119,6 +119,7 @@ export type Plugin = {
verified: boolean verified: boolean
label: Record<Locale, string> label: Record<Locale, string>
brief: Record<Locale, string> brief: Record<Locale, string>
description: Record<Locale, string>
// Repo readme.md content // Repo readme.md content
introduction: string introduction: string
repository: string repository: string

View File

@ -38,6 +38,7 @@ export const useMarketplace = (searchPluginText: string, filterPluginTags: strin
query: searchPluginText, query: searchPluginText,
tags: filterPluginTags, tags: filterPluginTags,
exclude, exclude,
type: 'plugin',
}) })
return return
} }
@ -46,6 +47,7 @@ export const useMarketplace = (searchPluginText: string, filterPluginTags: strin
query: searchPluginText, query: searchPluginText,
tags: filterPluginTags, tags: filterPluginTags,
exclude, exclude,
type: 'plugin',
}) })
} }
else { else {
@ -54,6 +56,7 @@ export const useMarketplace = (searchPluginText: string, filterPluginTags: strin
category: PluginType.tool, category: PluginType.tool,
condition: getMarketplaceListCondition(PluginType.tool), condition: getMarketplaceListCondition(PluginType.tool),
exclude, exclude,
type: 'plugin',
}) })
resetPlugins() resetPlugins()
} }

View File

@ -4,7 +4,7 @@ const translation = {
models: '模型', models: '模型',
tools: '工具', tools: '工具',
extensions: '扩展', extensions: '扩展',
bundles: '捆绑包', bundles: '插件集',
}, },
search: '搜索', search: '搜索',
allCategories: '所有类别', allCategories: '所有类别',

View File

@ -296,6 +296,7 @@ export const useMutationPluginsFromMarketplace = () => {
category, category,
tags, tags,
exclude, exclude,
type,
} = pluginsSearchParams } = pluginsSearchParams
return postMarketplace<{ data: PluginsFromMarketplaceResponse }>('/plugins/search/basic', { return postMarketplace<{ data: PluginsFromMarketplaceResponse }>('/plugins/search/basic', {
body: { body: {
@ -307,6 +308,7 @@ export const useMutationPluginsFromMarketplace = () => {
category: category !== 'all' ? category : '', category: category !== 'all' ? category : '',
tags, tags,
exclude, exclude,
type,
}, },
}) })
}, },