Merge branch 'feat/plugins' into dev/plugin-deploy
This commit is contained in:
commit
b858533a57
@ -8,7 +8,7 @@ const PluginList = async () => {
|
||||
return (
|
||||
<PluginPage
|
||||
plugins={<PluginsPanel />}
|
||||
marketplace={<Marketplace locale={locale} shouldExclude />}
|
||||
marketplace={<Marketplace locale={locale} shouldExclude pluginTypeSwitchClassName='top-[60px]' />}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -285,3 +285,25 @@ export const useMarketplace = (providers: ModelProvider[], searchText: string) =
|
||||
plugins: plugins?.filter(plugin => plugin.type !== 'bundle'),
|
||||
}
|
||||
}
|
||||
|
||||
export const useMarketplaceAllPlugins = () => {
|
||||
const {
|
||||
plugins,
|
||||
queryPlugins,
|
||||
isLoading,
|
||||
} = useMarketplacePlugins()
|
||||
|
||||
useEffect(() => {
|
||||
queryPlugins({
|
||||
query: '',
|
||||
category: PluginType.model,
|
||||
type: 'plugin',
|
||||
pageSize: 1000,
|
||||
})
|
||||
}, [queryPlugins])
|
||||
|
||||
return {
|
||||
plugins: plugins?.filter(plugin => plugin.type !== 'bundle'),
|
||||
isLoading,
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
import {
|
||||
useDefaultModel,
|
||||
useMarketplace,
|
||||
useMarketplaceAllPlugins,
|
||||
useUpdateModelList,
|
||||
useUpdateModelProviders,
|
||||
} from './hooks'
|
||||
@ -128,6 +129,10 @@ const ModelProviderPage = ({ searchText }: Props) => {
|
||||
marketplaceCollectionPluginsMap,
|
||||
isLoading: isPluginsLoading,
|
||||
} = useMarketplace(providers, searchText)
|
||||
const {
|
||||
plugins: allPlugins,
|
||||
isLoading: isAllPluginsLoading,
|
||||
} = useMarketplaceAllPlugins()
|
||||
|
||||
const cardRender = useCallback((plugin: Plugin) => {
|
||||
if (plugin.type === 'bundle')
|
||||
@ -206,12 +211,12 @@ const ModelProviderPage = ({ searchText }: Props) => {
|
||||
<div className='flex items-center mb-2 pt-2'>
|
||||
<span className='pr-1 text-text-tertiary system-sm-regular'>{t('common.modelProvider.discoverMore')}</span>
|
||||
<Link target="_blank" href={`${MARKETPLACE_URL_PREFIX}`} className='inline-flex items-center system-sm-medium text-text-accent'>
|
||||
Dify Marketplace
|
||||
{t('plugin.marketplace.difyMarketplace')}
|
||||
<RiArrowRightUpLine className='w-4 h-4' />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
{!collapse && isPluginsLoading && <Loading type='area' />}
|
||||
{!collapse && (isPluginsLoading || isAllPluginsLoading) && <Loading type='area' />}
|
||||
{
|
||||
!isPluginsLoading && (
|
||||
<List
|
||||
@ -225,6 +230,19 @@ const ModelProviderPage = ({ searchText }: Props) => {
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
!isAllPluginsLoading && (
|
||||
<List
|
||||
marketplaceCollections={[]}
|
||||
marketplaceCollectionPluginsMap={{}}
|
||||
plugins={allPlugins}
|
||||
showInstallButton
|
||||
locale={locale}
|
||||
cardContainerClassName='grid grid-cols-2 gap-2'
|
||||
cardRender={cardRender}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,10 +1,9 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { type PluginDeclaration, type PluginType, TaskStatus, type UpdateFromGitHubPayload } from '../../../types'
|
||||
import { type Plugin, type PluginDeclaration, TaskStatus, type UpdateFromGitHubPayload } from '../../../types'
|
||||
import Card from '../../../card'
|
||||
import Badge, { BadgeState } from '@/app/components/base/badge/index'
|
||||
import { pluginManifestToCardPluginProps } from '../../utils'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { updateFromGitHub } from '@/service/plugins'
|
||||
@ -12,13 +11,14 @@ import { useInstallPackageFromGitHub } from '@/service/use-plugins'
|
||||
import { RiLoader2Line } from '@remixicon/react'
|
||||
import { usePluginTaskList } from '@/service/use-plugins'
|
||||
import checkTaskStatus from '../../base/check-task-status'
|
||||
import useCheckInstalled from '@/app/components/plugins/install-plugin/hooks/use-check-installed'
|
||||
import { parseGitHubUrl } from '../../utils'
|
||||
import { useCategories } from '../../../hooks'
|
||||
import Version from '../../base/version'
|
||||
|
||||
type LoadedProps = {
|
||||
updatePayload: UpdateFromGitHubPayload
|
||||
uniqueIdentifier: string
|
||||
payload: PluginDeclaration
|
||||
payload: PluginDeclaration | Plugin
|
||||
repoUrl: string
|
||||
selectedVersion: string
|
||||
selectedPackage: string
|
||||
@ -41,12 +41,26 @@ const Loaded: React.FC<LoadedProps> = ({
|
||||
onFailed,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { categoriesMap } = useCategories()
|
||||
const toInstallVersion = payload.version
|
||||
const pluginId = (payload as Plugin).plugin_id
|
||||
const { installedInfo, isLoading } = useCheckInstalled({
|
||||
pluginIds: [pluginId],
|
||||
enabled: !!pluginId,
|
||||
})
|
||||
const installedInfoPayload = installedInfo?.[pluginId]
|
||||
const installedVersion = installedInfoPayload?.installedVersion
|
||||
const hasInstalled = !!installedVersion
|
||||
|
||||
const [isInstalling, setIsInstalling] = React.useState(false)
|
||||
const { mutateAsync: installPackageFromGitHub } = useInstallPackageFromGitHub()
|
||||
const { handleRefetch } = usePluginTaskList()
|
||||
const { check } = checkTaskStatus()
|
||||
|
||||
useEffect(() => {
|
||||
if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier)
|
||||
onInstalled()
|
||||
}, [hasInstalled])
|
||||
|
||||
const handleInstall = async () => {
|
||||
if (isInstalling) return
|
||||
setIsInstalling(true)
|
||||
@ -54,8 +68,9 @@ const Loaded: React.FC<LoadedProps> = ({
|
||||
try {
|
||||
const { owner, repo } = parseGitHubUrl(repoUrl)
|
||||
let taskId
|
||||
let isInstalled
|
||||
if (updatePayload) {
|
||||
const { all_installed: isInstalled, task_id } = await updateFromGitHub(
|
||||
const { all_installed, task_id } = await updateFromGitHub(
|
||||
`${owner}/${repo}`,
|
||||
selectedVersion,
|
||||
selectedPackage,
|
||||
@ -64,31 +79,41 @@ const Loaded: React.FC<LoadedProps> = ({
|
||||
)
|
||||
|
||||
taskId = task_id
|
||||
|
||||
if (isInstalled) {
|
||||
onInstalled()
|
||||
return
|
||||
}
|
||||
|
||||
handleRefetch()
|
||||
isInstalled = all_installed
|
||||
}
|
||||
else {
|
||||
const { all_installed: isInstalled, task_id } = await installPackageFromGitHub({
|
||||
repoUrl: `${owner}/${repo}`,
|
||||
selectedVersion,
|
||||
selectedPackage,
|
||||
uniqueIdentifier,
|
||||
})
|
||||
|
||||
taskId = task_id
|
||||
|
||||
if (isInstalled) {
|
||||
onInstalled()
|
||||
return
|
||||
if (hasInstalled) {
|
||||
const {
|
||||
all_installed,
|
||||
task_id,
|
||||
} = await updateFromGitHub(
|
||||
`${owner}/${repo}`,
|
||||
selectedVersion,
|
||||
selectedPackage,
|
||||
installedInfoPayload.uniqueIdentifier,
|
||||
uniqueIdentifier,
|
||||
)
|
||||
taskId = task_id
|
||||
isInstalled = all_installed
|
||||
}
|
||||
else {
|
||||
const { all_installed, task_id } = await installPackageFromGitHub({
|
||||
repoUrl: `${owner}/${repo}`,
|
||||
selectedVersion,
|
||||
selectedPackage,
|
||||
uniqueIdentifier,
|
||||
})
|
||||
|
||||
handleRefetch()
|
||||
taskId = task_id
|
||||
isInstalled = all_installed
|
||||
}
|
||||
}
|
||||
if (isInstalled) {
|
||||
onInstalled()
|
||||
return
|
||||
}
|
||||
|
||||
handleRefetch()
|
||||
|
||||
const { status, error } = await check({
|
||||
taskId,
|
||||
@ -120,8 +145,12 @@ const Loaded: React.FC<LoadedProps> = ({
|
||||
<div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'>
|
||||
<Card
|
||||
className='w-full'
|
||||
payload={{ ...pluginManifestToCardPluginProps(payload), type: categoriesMap[payload.category].label as PluginType }}
|
||||
titleLeft={<Badge className='mx-1' size="s" state={BadgeState.Default}>{payload.version}</Badge>}
|
||||
payload={pluginManifestToCardPluginProps(payload as PluginDeclaration)}
|
||||
titleLeft={!isLoading && <Version
|
||||
hasInstalled={hasInstalled}
|
||||
installedVersion={installedVersion}
|
||||
toInstallVersion={toInstallVersion}
|
||||
/>}
|
||||
/>
|
||||
</div>
|
||||
<div className='flex justify-end items-center gap-2 self-stretch mt-4'>
|
||||
@ -134,7 +163,7 @@ const Loaded: React.FC<LoadedProps> = ({
|
||||
variant='primary'
|
||||
className='min-w-[72px] flex space-x-0.5'
|
||||
onClick={handleInstall}
|
||||
disabled={isInstalling}
|
||||
disabled={isInstalling || isLoading}
|
||||
>
|
||||
{isInstalling && <RiLoader2Line className='w-4 h-4 animate-spin-slow' />}
|
||||
<span>{t(`${i18nPrefix}.${isInstalling ? 'installing' : 'install'}`)}</span>
|
||||
|
@ -45,15 +45,19 @@ export type MarketplaceContextValue = {
|
||||
handleFilterPluginTagsChange: (tags: string[]) => void
|
||||
activePluginType: string
|
||||
handleActivePluginTypeChange: (type: string) => void
|
||||
page: number
|
||||
handlePageChange: (page: number) => void
|
||||
plugins?: Plugin[]
|
||||
resetPlugins: () => void
|
||||
sort: PluginsSort
|
||||
handleSortChange: (sort: PluginsSort) => void
|
||||
handleQueryPluginsWhenNoCollection: () => void
|
||||
marketplaceCollectionsFromClient?: MarketplaceCollection[]
|
||||
setMarketplaceCollectionsFromClient: (collections: MarketplaceCollection[]) => void
|
||||
marketplaceCollectionPluginsMapFromClient?: Record<string, Plugin[]>
|
||||
setMarketplaceCollectionPluginsMapFromClient: (map: Record<string, Plugin[]>) => void
|
||||
isLoading: boolean
|
||||
isSuccessCollections: boolean
|
||||
}
|
||||
|
||||
export const MarketplaceContext = createContext<MarketplaceContextValue>({
|
||||
@ -65,15 +69,19 @@ export const MarketplaceContext = createContext<MarketplaceContextValue>({
|
||||
handleFilterPluginTagsChange: () => {},
|
||||
activePluginType: 'all',
|
||||
handleActivePluginTypeChange: () => {},
|
||||
page: 1,
|
||||
handlePageChange: () => {},
|
||||
plugins: undefined,
|
||||
resetPlugins: () => {},
|
||||
sort: DEFAULT_SORT,
|
||||
handleSortChange: () => {},
|
||||
handleQueryPluginsWhenNoCollection: () => {},
|
||||
marketplaceCollectionsFromClient: [],
|
||||
setMarketplaceCollectionsFromClient: () => {},
|
||||
marketplaceCollectionPluginsMapFromClient: {},
|
||||
setMarketplaceCollectionPluginsMapFromClient: () => {},
|
||||
isLoading: false,
|
||||
isSuccessCollections: false,
|
||||
})
|
||||
|
||||
type MarketplaceContextProviderProps = {
|
||||
@ -108,6 +116,8 @@ export const MarketplaceContextProvider = ({
|
||||
const filterPluginTagsRef = useRef(filterPluginTags)
|
||||
const [activePluginType, setActivePluginType] = useState(categoryFromSearchParams)
|
||||
const activePluginTypeRef = useRef(activePluginType)
|
||||
const [page, setPage] = useState(1)
|
||||
const pageRef = useRef(page)
|
||||
const [sort, setSort] = useState(DEFAULT_SORT)
|
||||
const sortRef = useRef(sort)
|
||||
const {
|
||||
@ -117,6 +127,7 @@ export const MarketplaceContextProvider = ({
|
||||
setMarketplaceCollectionPluginsMap: setMarketplaceCollectionPluginsMapFromClient,
|
||||
queryMarketplaceCollectionsAndPlugins,
|
||||
isLoading,
|
||||
isSuccess: isSuccessCollections,
|
||||
} = useMarketplaceCollectionsAndPlugins()
|
||||
const {
|
||||
plugins,
|
||||
@ -135,6 +146,7 @@ export const MarketplaceContextProvider = ({
|
||||
sortBy: sortRef.current.sortBy,
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
history.pushState({}, '', `/${searchParams?.language ? `?language=${searchParams?.language}` : ''}`)
|
||||
}
|
||||
@ -152,6 +164,8 @@ export const MarketplaceContextProvider = ({
|
||||
const handleSearchPluginTextChange = useCallback((text: string) => {
|
||||
setSearchPluginText(text)
|
||||
searchPluginTextRef.current = text
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
if (!searchPluginTextRef.current && !filterPluginTagsRef.current.length) {
|
||||
queryMarketplaceCollectionsAndPlugins({
|
||||
@ -172,12 +186,15 @@ export const MarketplaceContextProvider = ({
|
||||
sortBy: sortRef.current.sortBy,
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
page: pageRef.current,
|
||||
})
|
||||
}, [queryPluginsWithDebounced, queryMarketplaceCollectionsAndPlugins, resetPlugins, exclude])
|
||||
|
||||
const handleFilterPluginTagsChange = useCallback((tags: string[]) => {
|
||||
setFilterPluginTags(tags)
|
||||
filterPluginTagsRef.current = tags
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
if (!searchPluginTextRef.current && !filterPluginTagsRef.current.length) {
|
||||
queryMarketplaceCollectionsAndPlugins({
|
||||
@ -199,12 +216,15 @@ export const MarketplaceContextProvider = ({
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
}, [queryPlugins, resetPlugins, queryMarketplaceCollectionsAndPlugins, exclude])
|
||||
|
||||
const handleActivePluginTypeChange = useCallback((type: string) => {
|
||||
setActivePluginType(type)
|
||||
activePluginTypeRef.current = type
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
if (!searchPluginTextRef.current && !filterPluginTagsRef.current.length) {
|
||||
queryMarketplaceCollectionsAndPlugins({
|
||||
@ -226,12 +246,25 @@ export const MarketplaceContextProvider = ({
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
}, [queryPlugins, resetPlugins, queryMarketplaceCollectionsAndPlugins, exclude])
|
||||
|
||||
const handleSortChange = useCallback((sort: PluginsSort) => {
|
||||
setSort(sort)
|
||||
sortRef.current = sort
|
||||
const handlePageChange = useCallback(() => {
|
||||
setPage(pageRef.current + 1)
|
||||
pageRef.current++
|
||||
|
||||
if (!searchPluginTextRef.current && !filterPluginTagsRef.current.length) {
|
||||
queryMarketplaceCollectionsAndPlugins({
|
||||
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
|
||||
condition: getMarketplaceListCondition(activePluginTypeRef.current),
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
})
|
||||
resetPlugins()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
queryPlugins({
|
||||
query: searchPluginTextRef.current,
|
||||
@ -241,9 +274,43 @@ export const MarketplaceContextProvider = ({
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
}, [exclude, queryPlugins, queryMarketplaceCollectionsAndPlugins, resetPlugins])
|
||||
|
||||
const handleSortChange = useCallback((sort: PluginsSort) => {
|
||||
setSort(sort)
|
||||
sortRef.current = sort
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
queryPlugins({
|
||||
query: searchPluginTextRef.current,
|
||||
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
|
||||
tags: filterPluginTagsRef.current,
|
||||
sortBy: sortRef.current.sortBy,
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
}, [queryPlugins, exclude])
|
||||
|
||||
const handleQueryPluginsWhenNoCollection = useCallback(() => {
|
||||
queryPlugins({
|
||||
query: searchPluginTextRef.current,
|
||||
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
|
||||
tags: filterPluginTagsRef.current,
|
||||
sortBy: sortRef.current.sortBy,
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
}, [exclude, queryPlugins])
|
||||
|
||||
// useMarketplaceContainerScroll(handlePageChange)
|
||||
|
||||
return (
|
||||
<MarketplaceContext.Provider
|
||||
value={{
|
||||
@ -255,15 +322,19 @@ export const MarketplaceContextProvider = ({
|
||||
handleFilterPluginTagsChange,
|
||||
activePluginType,
|
||||
handleActivePluginTypeChange,
|
||||
page,
|
||||
handlePageChange,
|
||||
plugins,
|
||||
resetPlugins,
|
||||
sort,
|
||||
handleSortChange,
|
||||
handleQueryPluginsWhenNoCollection,
|
||||
marketplaceCollectionsFromClient,
|
||||
setMarketplaceCollectionsFromClient,
|
||||
marketplaceCollectionPluginsMapFromClient,
|
||||
setMarketplaceCollectionPluginsMapFromClient,
|
||||
isLoading: isLoading || isPluginsLoading,
|
||||
isSuccessCollections,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -23,16 +24,25 @@ import {
|
||||
|
||||
export const useMarketplaceCollectionsAndPlugins = () => {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [isSuccess, setIsSuccess] = useState(false)
|
||||
const [marketplaceCollections, setMarketplaceCollections] = useState<MarketplaceCollection[]>()
|
||||
const [marketplaceCollectionPluginsMap, setMarketplaceCollectionPluginsMap] = useState<Record<string, Plugin[]>>()
|
||||
|
||||
const queryMarketplaceCollectionsAndPlugins = useCallback(async (query?: CollectionsAndPluginsSearchParams) => {
|
||||
setIsLoading(true)
|
||||
const { marketplaceCollections, marketplaceCollectionPluginsMap } = await getMarketplaceCollectionsAndPlugins(query)
|
||||
setIsLoading(false)
|
||||
|
||||
setMarketplaceCollections(marketplaceCollections)
|
||||
setMarketplaceCollectionPluginsMap(marketplaceCollectionPluginsMap)
|
||||
try {
|
||||
setIsLoading(true)
|
||||
setIsSuccess(false)
|
||||
const { marketplaceCollections, marketplaceCollectionPluginsMap } = await getMarketplaceCollectionsAndPlugins(query)
|
||||
setIsLoading(false)
|
||||
setIsSuccess(true)
|
||||
setMarketplaceCollections(marketplaceCollections)
|
||||
setMarketplaceCollectionPluginsMap(marketplaceCollectionPluginsMap)
|
||||
}
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
catch (e) {
|
||||
setIsLoading(false)
|
||||
setIsSuccess(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return {
|
||||
@ -42,6 +52,7 @@ export const useMarketplaceCollectionsAndPlugins = () => {
|
||||
setMarketplaceCollectionPluginsMap,
|
||||
queryMarketplaceCollectionsAndPlugins,
|
||||
isLoading,
|
||||
isSuccess,
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +78,7 @@ export const useMarketplacePlugins = () => {
|
||||
plugins: data?.data?.plugins.map((plugin) => {
|
||||
return getFormattedPlugin(plugin)
|
||||
}),
|
||||
total: data?.data?.total,
|
||||
resetPlugins: reset,
|
||||
queryPlugins,
|
||||
queryPluginsWithDebounced,
|
||||
@ -84,3 +96,28 @@ export const useMixedTranslation = (localeFromOuter?: string) => {
|
||||
t,
|
||||
}
|
||||
}
|
||||
|
||||
export const useMarketplaceContainerScroll = (callback: () => void) => {
|
||||
const container = document.getElementById('marketplace-container')
|
||||
|
||||
const handleScroll = useCallback((e: Event) => {
|
||||
const target = e.target as HTMLDivElement
|
||||
const {
|
||||
scrollTop,
|
||||
scrollHeight,
|
||||
clientHeight,
|
||||
} = target
|
||||
if (scrollTop + clientHeight >= scrollHeight - 5 && scrollTop > 0)
|
||||
callback()
|
||||
}, [callback])
|
||||
|
||||
useEffect(() => {
|
||||
if (container)
|
||||
container.addEventListener('scroll', handleScroll)
|
||||
|
||||
return () => {
|
||||
if (container)
|
||||
container.removeEventListener('scroll', handleScroll)
|
||||
}
|
||||
}, [container, handleScroll])
|
||||
}
|
||||
|
@ -13,12 +13,14 @@ type MarketplaceProps = {
|
||||
showInstallButton?: boolean
|
||||
shouldExclude?: boolean
|
||||
searchParams?: SearchParams
|
||||
pluginTypeSwitchClassName?: string
|
||||
}
|
||||
const Marketplace = async ({
|
||||
locale,
|
||||
showInstallButton = true,
|
||||
shouldExclude,
|
||||
searchParams,
|
||||
pluginTypeSwitchClassName,
|
||||
}: MarketplaceProps) => {
|
||||
let marketplaceCollections: any = []
|
||||
let marketplaceCollectionPluginsMap = {}
|
||||
@ -34,7 +36,10 @@ const Marketplace = async ({
|
||||
<Description locale={locale} />
|
||||
<IntersectionLine />
|
||||
<SearchBoxWrapper locale={locale} />
|
||||
<PluginTypeSwitch locale={locale} />
|
||||
<PluginTypeSwitch
|
||||
locale={locale}
|
||||
className={pluginTypeSwitchClassName}
|
||||
/>
|
||||
<ListWrapper
|
||||
locale={locale}
|
||||
marketplaceCollections={marketplaceCollections}
|
||||
|
@ -1,4 +1,5 @@
|
||||
'use client'
|
||||
import { useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { Plugin } from '../../types'
|
||||
import type { MarketplaceCollection } from '../types'
|
||||
@ -24,6 +25,13 @@ const ListWrapper = ({
|
||||
const marketplaceCollectionsFromClient = useMarketplaceContext(v => v.marketplaceCollectionsFromClient)
|
||||
const marketplaceCollectionPluginsMapFromClient = useMarketplaceContext(v => v.marketplaceCollectionPluginsMapFromClient)
|
||||
const isLoading = useMarketplaceContext(v => v.isLoading)
|
||||
const isSuccessCollections = useMarketplaceContext(v => v.isSuccessCollections)
|
||||
const handleQueryPluginsWhenNoCollection = useMarketplaceContext(v => v.handleQueryPluginsWhenNoCollection)
|
||||
|
||||
useEffect(() => {
|
||||
if (!marketplaceCollectionsFromClient?.length && isSuccessCollections)
|
||||
handleQueryPluginsWhenNoCollection()
|
||||
}, [handleQueryPluginsWhenNoCollection, marketplaceCollections, marketplaceCollectionsFromClient, isSuccessCollections])
|
||||
|
||||
return (
|
||||
<div className='relative flex flex-col grow px-12 py-2 bg-background-default-subtle'>
|
||||
|
@ -19,9 +19,11 @@ export const PLUGIN_TYPE_SEARCH_MAP = {
|
||||
}
|
||||
type PluginTypeSwitchProps = {
|
||||
locale?: string
|
||||
className?: string
|
||||
}
|
||||
const PluginTypeSwitch = ({
|
||||
locale,
|
||||
className,
|
||||
}: PluginTypeSwitchProps) => {
|
||||
const { t } = useMixedTranslation(locale)
|
||||
const activePluginType = useMarketplaceContext(s => s.activePluginType)
|
||||
@ -57,7 +59,8 @@ const PluginTypeSwitch = ({
|
||||
|
||||
return (
|
||||
<div className={cn(
|
||||
'sticky top-[60px] shrink-0 flex items-center justify-center py-3 bg-background-body space-x-2 z-10',
|
||||
'sticky top-[56px] shrink-0 flex items-center justify-center py-3 bg-background-body space-x-2 z-10',
|
||||
className,
|
||||
)}>
|
||||
{
|
||||
options.map(option => (
|
||||
|
@ -312,6 +312,7 @@ export type UninstallPluginResponse = {
|
||||
|
||||
export type PluginsFromMarketplaceResponse = {
|
||||
plugins: Plugin[]
|
||||
total: number
|
||||
}
|
||||
export type PluginsFromMarketplaceByInfoResponse = {
|
||||
list: {
|
||||
|
@ -297,11 +297,12 @@ export const useMutationPluginsFromMarketplace = () => {
|
||||
tags,
|
||||
exclude,
|
||||
type,
|
||||
page = 1,
|
||||
} = pluginsSearchParams
|
||||
return postMarketplace<{ data: PluginsFromMarketplaceResponse }>('/plugins/search/basic', {
|
||||
body: {
|
||||
page: 1,
|
||||
page_size: 10,
|
||||
page,
|
||||
page_size: 100,
|
||||
query,
|
||||
sort_by: sortBy,
|
||||
sort_order: sortOrder,
|
||||
|
Loading…
Reference in New Issue
Block a user