feat: marketplace list

This commit is contained in:
StyleZhang 2024-10-29 14:44:30 +08:00
parent 36c01d89c9
commit e65a47cff7
6 changed files with 102 additions and 54 deletions

View File

@ -13,6 +13,7 @@ import { useDebounceFn } from 'ahooks'
import { PLUGIN_TYPE_SEARCH_MAP } from './plugin-type-switch' import { PLUGIN_TYPE_SEARCH_MAP } from './plugin-type-switch'
import type { Plugin } from '../types' import type { Plugin } from '../types'
import type { PluginsSearchParams } from './types' import type { PluginsSearchParams } from './types'
import { getMarketplacePlugins } from './utils'
export type MarketplaceContextValue = { export type MarketplaceContextValue = {
intersected: boolean intersected: boolean
@ -57,31 +58,10 @@ export const MarketplaceContextProvider = ({
const [activePluginType, setActivePluginType] = useState(PLUGIN_TYPE_SEARCH_MAP.all) const [activePluginType, setActivePluginType] = useState(PLUGIN_TYPE_SEARCH_MAP.all)
const [plugins, setPlugins] = useState<Plugin[]>() const [plugins, setPlugins] = useState<Plugin[]>()
const handleUpdatePlugins = useCallback((query: PluginsSearchParams) => { const handleUpdatePlugins = useCallback(async (query: PluginsSearchParams) => {
const fetchPlugins = async () => { const { marketplacePlugins } = await getMarketplacePlugins(query)
const response = await fetch(
'https://marketplace.dify.dev/api/v1/plugins/search/basic',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: query.query,
page: 1,
page_size: 10,
sort_by: query.sortBy,
sort_order: query.sortOrder,
category: query.category,
tag: query.tag,
}),
},
)
const data = await response.json()
setPlugins(data.data.plugins)
}
fetchPlugins() setPlugins(marketplacePlugins)
}, []) }, [])
const { run: handleUpdatePluginsWithDebounced } = useDebounceFn(handleUpdatePlugins, { const { run: handleUpdatePluginsWithDebounced } = useDebounceFn(handleUpdatePlugins, {

View File

@ -1,24 +1,13 @@
import type { Plugin } from '../types'
import { MarketplaceContextProvider } from './context' import { MarketplaceContextProvider } from './context'
import Description from './description' import Description from './description'
import IntersectionLine from './intersection-line' import IntersectionLine from './intersection-line'
import SearchBox from './search-box' import SearchBox from './search-box'
import PluginTypeSwitch from './plugin-type-switch' import PluginTypeSwitch from './plugin-type-switch'
import ListWrapper from './list/list-wrapper' import ListWrapper from './list/list-wrapper'
import type { MarketplaceCollection } from './types' import { getMarketplaceCollectionsAndPlugins } from './utils'
const Marketplace = async () => { const Marketplace = async () => {
const marketplaceCollectionsData = await globalThis.fetch('https://marketplace.dify.dev/api/v1/collections') const { marketplaceCollections, marketplaceCollectionPluginsMap } = await getMarketplaceCollectionsAndPlugins()
const marketplaceCollectionsDataJson = await marketplaceCollectionsData.json()
const marketplaceCollections = marketplaceCollectionsDataJson.data.collections
const marketplaceCollectionPluginsMap = {} as Record<string, Plugin[]>
await Promise.all(marketplaceCollections.map(async (collection: MarketplaceCollection) => {
const marketplaceCollectionPluginsData = await globalThis.fetch(`https://marketplace.dify.dev/api/v1/collections/${collection.name}/plugins`)
const marketplaceCollectionPluginsDataJson = await marketplaceCollectionPluginsData.json()
const plugins = marketplaceCollectionPluginsDataJson.data.plugins
marketplaceCollectionPluginsMap[collection.name] = plugins
}))
return ( return (
<MarketplaceContextProvider> <MarketplaceContextProvider>

View File

@ -27,7 +27,7 @@ const List = ({
} }
{ {
plugins && ( plugins && (
<div className='grid grid-cols-4 gap-3 mt-2'> <div className='grid grid-cols-4 gap-3'>
{ {
plugins.map(plugin => ( plugins.map(plugin => (
<Card <Card

View File

@ -0,0 +1,67 @@
import type { Plugin } from '@/app/components/plugins/types'
import type {
MarketplaceCollection,
PluginsSearchParams,
} from '@/app/components/plugins/marketplace/types'
const MARKETPLACE_API_URL = 'https://marketplace.dify.dev/api/v1'
export const getMarketplaceCollectionsAndPlugins = async () => {
let marketplaceCollections = [] as MarketplaceCollection[]
let marketplaceCollectionPluginsMap = {} as Record<string, Plugin[]>
try {
const marketplaceCollectionsData = await globalThis.fetch(`${MARKETPLACE_API_URL}/collections`)
const marketplaceCollectionsDataJson = await marketplaceCollectionsData.json()
marketplaceCollections = marketplaceCollectionsDataJson.data.collections
await Promise.all(marketplaceCollections.map(async (collection: MarketplaceCollection) => {
const marketplaceCollectionPluginsData = await globalThis.fetch(`${MARKETPLACE_API_URL}/collections/${collection.name}/plugins`)
const marketplaceCollectionPluginsDataJson = await marketplaceCollectionPluginsData.json()
const plugins = marketplaceCollectionPluginsDataJson.data.plugins
marketplaceCollectionPluginsMap[collection.name] = plugins
}))
}
// eslint-disable-next-line unused-imports/no-unused-vars
catch (e) {
marketplaceCollections = []
marketplaceCollectionPluginsMap = {}
}
return {
marketplaceCollections,
marketplaceCollectionPluginsMap,
}
}
export const getMarketplacePlugins = async (query: PluginsSearchParams) => {
let marketplacePlugins = [] as Plugin[]
try {
const marketplacePluginsData = await globalThis.fetch(
`${MARKETPLACE_API_URL}/plugins`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
page: 1,
page_size: 10,
query: query.query,
sort_by: query.sortBy,
sort_order: query.sortOrder,
category: query.category,
tag: query.tag,
}),
},
)
const marketplacePluginsDataJson = await marketplacePluginsData.json()
marketplacePlugins = marketplacePluginsDataJson.data.plugins
}
// eslint-disable-next-line unused-imports/no-unused-vars
catch (e) {
marketplacePlugins = []
}
return {
marketplacePlugins,
}
}

View File

@ -5,22 +5,16 @@ import {
} from 'react' } from 'react'
import type { Plugin } from '@/app/components/plugins/types' import type { Plugin } from '@/app/components/plugins/types'
import type { MarketplaceCollection } from '@/app/components/plugins/marketplace/types' import type { MarketplaceCollection } from '@/app/components/plugins/marketplace/types'
import { getMarketplaceCollectionsAndPlugins } from '@/app/components/plugins/marketplace/utils'
export const useMarketplace = () => { export const useMarketplace = () => {
const [marketplaceCollections, setMarketplaceCollections] = useState<MarketplaceCollection[]>([]) const [marketplaceCollections, setMarketplaceCollections] = useState<MarketplaceCollection[]>([])
const [marketplaceCollectionPluginsMap, setMarketplaceCollectionPluginsMap] = useState<Record<string, Plugin[]>>({}) const [marketplaceCollectionPluginsMap, setMarketplaceCollectionPluginsMap] = useState<Record<string, Plugin[]>>({})
const [isLoading, setIsLoading] = useState(true)
const getMarketplaceCollections = useCallback(async () => { const getMarketplaceCollections = useCallback(async () => {
const marketplaceCollectionsData = await globalThis.fetch('https://marketplace.dify.dev/api/v1/collections') setIsLoading(true)
const marketplaceCollectionsDataJson = await marketplaceCollectionsData.json() const { marketplaceCollections, marketplaceCollectionPluginsMap } = await getMarketplaceCollectionsAndPlugins()
const marketplaceCollections = marketplaceCollectionsDataJson.data.collections setIsLoading(false)
const marketplaceCollectionPluginsMap = {} as Record<string, Plugin[]>
await Promise.all(marketplaceCollections.map(async (collection: MarketplaceCollection) => {
const marketplaceCollectionPluginsData = await globalThis.fetch(`https://marketplace.dify.dev/api/v1/collections/${collection.name}/plugins`)
const marketplaceCollectionPluginsDataJson = await marketplaceCollectionPluginsData.json()
const plugins = marketplaceCollectionPluginsDataJson.data.plugins
marketplaceCollectionPluginsMap[collection.name] = plugins
}))
setMarketplaceCollections(marketplaceCollections) setMarketplaceCollections(marketplaceCollections)
setMarketplaceCollectionPluginsMap(marketplaceCollectionPluginsMap) setMarketplaceCollectionPluginsMap(marketplaceCollectionPluginsMap)
}, []) }, [])
@ -29,6 +23,7 @@ export const useMarketplace = () => {
}, [getMarketplaceCollections]) }, [getMarketplaceCollections])
return { return {
isLoading,
marketplaceCollections, marketplaceCollections,
marketplaceCollectionPluginsMap, marketplaceCollectionPluginsMap,
} }

View File

@ -1,6 +1,7 @@
import { RiArrowUpDoubleLine } from '@remixicon/react' import { RiArrowUpDoubleLine } from '@remixicon/react'
import { useMarketplace } from './hooks' import { useMarketplace } from './hooks'
import List from '@/app/components/plugins/marketplace/list' import List from '@/app/components/plugins/marketplace/list'
import Loading from '@/app/components/base/loading'
type MarketplaceProps = { type MarketplaceProps = {
onMarketplaceScroll: () => void onMarketplaceScroll: () => void
@ -8,7 +9,12 @@ type MarketplaceProps = {
const Marketplace = ({ const Marketplace = ({
onMarketplaceScroll, onMarketplaceScroll,
}: MarketplaceProps) => { }: MarketplaceProps) => {
const { marketplaceCollections, marketplaceCollectionPluginsMap } = useMarketplace() const {
isLoading,
marketplaceCollections,
marketplaceCollectionPluginsMap,
} = useMarketplace()
return ( return (
<div className='shrink-0 sticky -bottom-[442px] h-[530px] overflow-y-auto px-12 py-2 pt-0 bg-background-default-subtle'> <div className='shrink-0 sticky -bottom-[442px] h-[530px] overflow-y-auto px-12 py-2 pt-0 bg-background-default-subtle'>
<RiArrowUpDoubleLine <RiArrowUpDoubleLine
@ -37,10 +43,21 @@ const Marketplace = ({
in Dify Marketplace in Dify Marketplace
</div> </div>
</div> </div>
{
isLoading && (
<div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'>
<Loading />
</div>
)
}
{
!isLoading && (
<List <List
marketplaceCollections={marketplaceCollections} marketplaceCollections={marketplaceCollections}
marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap} marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap}
/> />
)
}
</div> </div>
) )
} }