mirror of https://github.com/langgenius/dify.git
fix: marketplace list
This commit is contained in:
parent
0e419a7a16
commit
0e70e72594
|
|
@ -28,6 +28,7 @@ import type {
|
|||
import { DEFAULT_SORT } from './constants'
|
||||
import {
|
||||
useMarketplaceCollectionsAndPlugins,
|
||||
useMarketplaceContainerScroll,
|
||||
useMarketplacePlugins,
|
||||
} from './hooks'
|
||||
import {
|
||||
|
|
@ -51,7 +52,7 @@ export type MarketplaceContextValue = {
|
|||
resetPlugins: () => void
|
||||
sort: PluginsSort
|
||||
handleSortChange: (sort: PluginsSort) => void
|
||||
handleQueryPluginsWhenNoCollection: () => void
|
||||
handleQueryPlugins: () => void
|
||||
marketplaceCollectionsFromClient?: MarketplaceCollection[]
|
||||
setMarketplaceCollectionsFromClient: (collections: MarketplaceCollection[]) => void
|
||||
marketplaceCollectionPluginsMapFromClient?: Record<string, Plugin[]>
|
||||
|
|
@ -75,7 +76,7 @@ export const MarketplaceContext = createContext<MarketplaceContextValue>({
|
|||
resetPlugins: () => {},
|
||||
sort: DEFAULT_SORT,
|
||||
handleSortChange: () => {},
|
||||
handleQueryPluginsWhenNoCollection: () => {},
|
||||
handleQueryPlugins: () => {},
|
||||
marketplaceCollectionsFromClient: [],
|
||||
setMarketplaceCollectionsFromClient: () => {},
|
||||
marketplaceCollectionPluginsMapFromClient: {},
|
||||
|
|
@ -88,6 +89,7 @@ type MarketplaceContextProviderProps = {
|
|||
children: ReactNode
|
||||
searchParams?: SearchParams
|
||||
shouldExclude?: boolean
|
||||
scrollContainerId?: string
|
||||
}
|
||||
|
||||
export function useMarketplaceContext(selector: (value: MarketplaceContextValue) => any) {
|
||||
|
|
@ -98,6 +100,7 @@ export const MarketplaceContextProvider = ({
|
|||
children,
|
||||
searchParams,
|
||||
shouldExclude,
|
||||
scrollContainerId,
|
||||
}: MarketplaceContextProviderProps) => {
|
||||
const { data, isSuccess } = useInstalledPluginList(!shouldExclude)
|
||||
const exclude = useMemo(() => {
|
||||
|
|
@ -131,6 +134,7 @@ export const MarketplaceContextProvider = ({
|
|||
} = useMarketplaceCollectionsAndPlugins()
|
||||
const {
|
||||
plugins,
|
||||
total: pluginsTotal,
|
||||
resetPlugins,
|
||||
queryPlugins,
|
||||
queryPluginsWithDebounced,
|
||||
|
|
@ -161,34 +165,60 @@ export const MarketplaceContextProvider = ({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [queryPlugins, queryMarketplaceCollectionsAndPlugins, isSuccess, exclude])
|
||||
|
||||
const handleQueryMarketplaceCollectionsAndPlugins = useCallback(() => {
|
||||
queryMarketplaceCollectionsAndPlugins({
|
||||
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
|
||||
condition: getMarketplaceListCondition(activePluginTypeRef.current),
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
})
|
||||
resetPlugins()
|
||||
}, [exclude, queryMarketplaceCollectionsAndPlugins, resetPlugins])
|
||||
|
||||
const handleQueryPlugins = useCallback((debounced?: boolean) => {
|
||||
if (debounced) {
|
||||
queryPluginsWithDebounced({
|
||||
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,
|
||||
})
|
||||
}
|
||||
else {
|
||||
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, queryPluginsWithDebounced, queryPlugins])
|
||||
|
||||
const handleQuery = useCallback((debounced?: boolean) => {
|
||||
if (!searchPluginTextRef.current && !filterPluginTagsRef.current.length) {
|
||||
handleQueryMarketplaceCollectionsAndPlugins()
|
||||
return
|
||||
}
|
||||
|
||||
handleQueryPlugins(debounced)
|
||||
}, [handleQueryMarketplaceCollectionsAndPlugins, handleQueryPlugins])
|
||||
|
||||
const handleSearchPluginTextChange = useCallback((text: string) => {
|
||||
setSearchPluginText(text)
|
||||
searchPluginTextRef.current = text
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
queryPluginsWithDebounced({
|
||||
query: text,
|
||||
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
|
||||
tags: filterPluginTagsRef.current,
|
||||
sortBy: sortRef.current.sortBy,
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
page: pageRef.current,
|
||||
})
|
||||
}, [queryPluginsWithDebounced, queryMarketplaceCollectionsAndPlugins, resetPlugins, exclude])
|
||||
handleQuery(true)
|
||||
}, [handleQuery])
|
||||
|
||||
const handleFilterPluginTagsChange = useCallback((tags: string[]) => {
|
||||
setFilterPluginTags(tags)
|
||||
|
|
@ -196,29 +226,8 @@ export const MarketplaceContextProvider = ({
|
|||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
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,
|
||||
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
|
||||
tags,
|
||||
sortBy: sortRef.current.sortBy,
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
}, [queryPlugins, resetPlugins, queryMarketplaceCollectionsAndPlugins, exclude])
|
||||
handleQuery()
|
||||
}, [handleQuery])
|
||||
|
||||
const handleActivePluginTypeChange = useCallback((type: string) => {
|
||||
setActivePluginType(type)
|
||||
|
|
@ -226,57 +235,8 @@ export const MarketplaceContextProvider = ({
|
|||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
if (!searchPluginTextRef.current && !filterPluginTagsRef.current.length) {
|
||||
queryMarketplaceCollectionsAndPlugins({
|
||||
category: type === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : type,
|
||||
condition: getMarketplaceListCondition(type),
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
})
|
||||
resetPlugins()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
queryPlugins({
|
||||
query: searchPluginTextRef.current,
|
||||
category: type === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : type,
|
||||
tags: filterPluginTagsRef.current,
|
||||
sortBy: sortRef.current.sortBy,
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
}, [queryPlugins, resetPlugins, queryMarketplaceCollectionsAndPlugins, exclude])
|
||||
|
||||
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,
|
||||
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, queryMarketplaceCollectionsAndPlugins, resetPlugins])
|
||||
handleQuery()
|
||||
}, [handleQuery])
|
||||
|
||||
const handleSortChange = useCallback((sort: PluginsSort) => {
|
||||
setSort(sort)
|
||||
|
|
@ -284,32 +244,19 @@ export const MarketplaceContextProvider = ({
|
|||
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])
|
||||
handleQueryPlugins()
|
||||
}, [handleQueryPlugins])
|
||||
|
||||
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])
|
||||
const handlePageChange = useCallback(() => {
|
||||
if (pluginsTotal && plugins && pluginsTotal > plugins.length && (!!searchPluginTextRef.current || !!filterPluginTagsRef.current.length)) {
|
||||
setPage(pageRef.current + 1)
|
||||
pageRef.current++
|
||||
|
||||
// useMarketplaceContainerScroll(handlePageChange)
|
||||
handleQueryPlugins()
|
||||
}
|
||||
}, [handleQueryPlugins, plugins, pluginsTotal])
|
||||
|
||||
useMarketplaceContainerScroll(handlePageChange, scrollContainerId)
|
||||
|
||||
return (
|
||||
<MarketplaceContext.Provider
|
||||
|
|
@ -328,7 +275,7 @@ export const MarketplaceContextProvider = ({
|
|||
resetPlugins,
|
||||
sort,
|
||||
handleSortChange,
|
||||
handleQueryPluginsWhenNoCollection,
|
||||
handleQueryPlugins,
|
||||
marketplaceCollectionsFromClient,
|
||||
setMarketplaceCollectionsFromClient,
|
||||
marketplaceCollectionPluginsMapFromClient,
|
||||
|
|
|
|||
|
|
@ -59,27 +59,46 @@ export const useMarketplaceCollectionsAndPlugins = () => {
|
|||
export const useMarketplacePlugins = () => {
|
||||
const {
|
||||
data,
|
||||
mutate,
|
||||
mutateAsync,
|
||||
reset,
|
||||
isPending,
|
||||
} = useMutationPluginsFromMarketplace()
|
||||
|
||||
const [prevPlugins, setPrevPlugins] = useState<Plugin[] | undefined>()
|
||||
const resetPlugins = useCallback(() => {
|
||||
reset()
|
||||
setPrevPlugins(undefined)
|
||||
}, [reset])
|
||||
const handleUpdatePlugins = useCallback((pluginsSearchParams: PluginsSearchParams) => {
|
||||
mutateAsync(pluginsSearchParams).then((res) => {
|
||||
const currentPage = pluginsSearchParams.page || 1
|
||||
const resPlugins = res.data.plugins
|
||||
if (currentPage > 1) {
|
||||
setPrevPlugins(prevPlugins => [...(prevPlugins || []), ...resPlugins.map((plugin) => {
|
||||
return getFormattedPlugin(plugin)
|
||||
})])
|
||||
}
|
||||
else {
|
||||
setPrevPlugins(resPlugins.map((plugin) => {
|
||||
return getFormattedPlugin(plugin)
|
||||
}))
|
||||
}
|
||||
})
|
||||
}, [mutateAsync])
|
||||
const queryPlugins = useCallback((pluginsSearchParams: PluginsSearchParams) => {
|
||||
mutate(pluginsSearchParams)
|
||||
}, [mutate])
|
||||
handleUpdatePlugins(pluginsSearchParams)
|
||||
}, [handleUpdatePlugins])
|
||||
|
||||
const { run: queryPluginsWithDebounced } = useDebounceFn((pluginsSearchParams: PluginsSearchParams) => {
|
||||
mutate(pluginsSearchParams)
|
||||
handleUpdatePlugins(pluginsSearchParams)
|
||||
}, {
|
||||
wait: 500,
|
||||
})
|
||||
|
||||
return {
|
||||
plugins: data?.data?.plugins.map((plugin) => {
|
||||
return getFormattedPlugin(plugin)
|
||||
}),
|
||||
plugins: prevPlugins,
|
||||
total: data?.data?.total,
|
||||
resetPlugins: reset,
|
||||
resetPlugins,
|
||||
queryPlugins,
|
||||
queryPluginsWithDebounced,
|
||||
isLoading: isPending,
|
||||
|
|
@ -97,8 +116,11 @@ export const useMixedTranslation = (localeFromOuter?: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const useMarketplaceContainerScroll = (callback: () => void) => {
|
||||
const container = document.getElementById('marketplace-container')
|
||||
export const useMarketplaceContainerScroll = (
|
||||
callback: () => void,
|
||||
scrollContainerId = 'marketplace-container',
|
||||
) => {
|
||||
const container = document.getElementById(scrollContainerId)
|
||||
|
||||
const handleScroll = useCallback((e: Event) => {
|
||||
const target = e.target as HTMLDivElement
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ type MarketplaceProps = {
|
|||
shouldExclude?: boolean
|
||||
searchParams?: SearchParams
|
||||
pluginTypeSwitchClassName?: string
|
||||
intersectionContainerId?: string
|
||||
scrollContainerId?: string
|
||||
}
|
||||
const Marketplace = async ({
|
||||
locale,
|
||||
|
|
@ -21,6 +23,8 @@ const Marketplace = async ({
|
|||
shouldExclude,
|
||||
searchParams,
|
||||
pluginTypeSwitchClassName,
|
||||
intersectionContainerId,
|
||||
scrollContainerId,
|
||||
}: MarketplaceProps) => {
|
||||
let marketplaceCollections: any = []
|
||||
let marketplaceCollectionPluginsMap = {}
|
||||
|
|
@ -32,9 +36,13 @@ const Marketplace = async ({
|
|||
|
||||
return (
|
||||
<TanstackQueryIniter>
|
||||
<MarketplaceContextProvider searchParams={searchParams} shouldExclude={shouldExclude}>
|
||||
<MarketplaceContextProvider
|
||||
searchParams={searchParams}
|
||||
shouldExclude={shouldExclude}
|
||||
scrollContainerId={scrollContainerId}
|
||||
>
|
||||
<Description locale={locale} />
|
||||
<IntersectionLine />
|
||||
<IntersectionLine intersectionContainerId={intersectionContainerId} />
|
||||
<SearchBoxWrapper locale={locale} />
|
||||
<PluginTypeSwitch
|
||||
locale={locale}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ import { useMarketplaceContext } from '@/app/components/plugins/marketplace/cont
|
|||
|
||||
export const useScrollIntersection = (
|
||||
anchorRef: React.RefObject<HTMLDivElement>,
|
||||
intersectionContainerId = 'marketplace-container',
|
||||
) => {
|
||||
const intersected = useMarketplaceContext(v => v.intersected)
|
||||
const setIntersected = useMarketplaceContext(v => v.setIntersected)
|
||||
|
||||
useEffect(() => {
|
||||
const container = document.getElementById('marketplace-container')
|
||||
const container = document.getElementById(intersectionContainerId)
|
||||
let observer: IntersectionObserver | undefined
|
||||
if (container && anchorRef.current) {
|
||||
observer = new IntersectionObserver((entries) => {
|
||||
|
|
@ -25,5 +26,5 @@ export const useScrollIntersection = (
|
|||
observer.observe(anchorRef.current)
|
||||
}
|
||||
return () => observer?.disconnect()
|
||||
}, [anchorRef, intersected, setIntersected])
|
||||
}, [anchorRef, intersected, setIntersected, intersectionContainerId])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,15 @@
|
|||
import { useRef } from 'react'
|
||||
import { useScrollIntersection } from './hooks'
|
||||
|
||||
const IntersectionLine = () => {
|
||||
type IntersectionLineProps = {
|
||||
intersectionContainerId?: string
|
||||
}
|
||||
const IntersectionLine = ({
|
||||
intersectionContainerId,
|
||||
}: IntersectionLineProps) => {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
|
||||
useScrollIntersection(ref)
|
||||
useScrollIntersection(ref, intersectionContainerId)
|
||||
|
||||
return (
|
||||
<div ref={ref} className='mb-4 h-[1px] bg-transparent'></div>
|
||||
|
|
|
|||
|
|
@ -26,18 +26,19 @@ const ListWrapper = ({
|
|||
const marketplaceCollectionPluginsMapFromClient = useMarketplaceContext(v => v.marketplaceCollectionPluginsMapFromClient)
|
||||
const isLoading = useMarketplaceContext(v => v.isLoading)
|
||||
const isSuccessCollections = useMarketplaceContext(v => v.isSuccessCollections)
|
||||
const handleQueryPluginsWhenNoCollection = useMarketplaceContext(v => v.handleQueryPluginsWhenNoCollection)
|
||||
const handleQueryPlugins = useMarketplaceContext(v => v.handleQueryPlugins)
|
||||
const page = useMarketplaceContext(v => v.page)
|
||||
|
||||
useEffect(() => {
|
||||
if (!marketplaceCollectionsFromClient?.length && isSuccessCollections)
|
||||
handleQueryPluginsWhenNoCollection()
|
||||
}, [handleQueryPluginsWhenNoCollection, marketplaceCollections, marketplaceCollectionsFromClient, isSuccessCollections])
|
||||
handleQueryPlugins()
|
||||
}, [handleQueryPlugins, marketplaceCollections, marketplaceCollectionsFromClient, isSuccessCollections])
|
||||
|
||||
return (
|
||||
<div className='relative flex flex-col grow px-12 py-2 bg-background-default-subtle'>
|
||||
{
|
||||
plugins && (
|
||||
<div className='flex items-center mb-4 pt-3'>
|
||||
<div className='top-5 flex items-center mb-4 pt-3'>
|
||||
<div className='title-xl-semi-bold text-text-primary'>{t('plugin.marketplace.pluginsResult', { num: plugins.length })}</div>
|
||||
<div className='mx-3 w-[1px] h-3.5 bg-divider-regular'></div>
|
||||
<SortDropdown />
|
||||
|
|
@ -45,14 +46,14 @@ const ListWrapper = ({
|
|||
)
|
||||
}
|
||||
{
|
||||
isLoading && (
|
||||
isLoading && page === 1 && (
|
||||
<div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'>
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
!isLoading && (
|
||||
(!isLoading || page > 1) && (
|
||||
<List
|
||||
marketplaceCollections={marketplaceCollectionsFromClient || marketplaceCollections}
|
||||
marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMapFromClient || marketplaceCollectionPluginsMap}
|
||||
|
|
|
|||
|
|
@ -298,11 +298,12 @@ export const useMutationPluginsFromMarketplace = () => {
|
|||
exclude,
|
||||
type,
|
||||
page = 1,
|
||||
pageSize = 20,
|
||||
} = pluginsSearchParams
|
||||
return postMarketplace<{ data: PluginsFromMarketplaceResponse }>('/plugins/search/basic', {
|
||||
body: {
|
||||
page,
|
||||
page_size: 100,
|
||||
page_size: pageSize,
|
||||
query,
|
||||
sort_by: sortBy,
|
||||
sort_order: sortOrder,
|
||||
|
|
|
|||
Loading…
Reference in New Issue