mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 02:18:08 +08:00
feat: add pagination for plugin page (#20151)
This commit is contained in:
@ -1,20 +1,23 @@
|
||||
'use client'
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { FilterState } from './filter-management'
|
||||
import FilterManagement from './filter-management'
|
||||
import List from './list'
|
||||
import { useInstalledLatestVersion, useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import { useInstalledLatestVersion, useInstalledPluginListWithPagination, useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import PluginDetailPanel from '@/app/components/plugins/plugin-detail-panel'
|
||||
import { usePluginPageContext } from './context'
|
||||
import { useDebounceFn } from 'ahooks'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Empty from './empty'
|
||||
import Loading from '../../base/loading'
|
||||
import { PluginSource } from '../types'
|
||||
|
||||
const PluginsPanel = () => {
|
||||
const { t } = useTranslation()
|
||||
const filters = usePluginPageContext(v => v.filters) as FilterState
|
||||
const setFilters = usePluginPageContext(v => v.setFilters)
|
||||
const { data: pluginList, isLoading: isPluginListLoading } = useInstalledPluginList()
|
||||
const { data: pluginList, isLoading: isPluginListLoading, isFetching, isLastPage, loadNextPage } = useInstalledPluginListWithPagination()
|
||||
const { data: installedLatestVersion } = useInstalledLatestVersion(
|
||||
pluginList?.plugins
|
||||
.filter(plugin => plugin.source === PluginSource.marketplace)
|
||||
@ -64,10 +67,16 @@ const PluginsPanel = () => {
|
||||
/>
|
||||
</div>
|
||||
{isPluginListLoading ? <Loading type='app' /> : (filteredList?.length ?? 0) > 0 ? (
|
||||
<div className='flex grow flex-wrap content-start items-start gap-2 self-stretch px-12'>
|
||||
<div className='flex grow flex-wrap content-start items-start justify-center gap-2 self-stretch px-12'>
|
||||
<div className='w-full'>
|
||||
<List pluginList={filteredList || []} />
|
||||
</div>
|
||||
{!isLastPage && !isFetching && (
|
||||
<Button onClick={loadNextPage}>
|
||||
{t('workflow.common.loadMore')}
|
||||
</Button>
|
||||
)}
|
||||
{isFetching && <div className='system-md-semibold text-text-secondary'>{t('appLog.detail.loading')}</div>}
|
||||
</div>
|
||||
) : (
|
||||
<Empty />
|
||||
|
||||
@ -325,6 +325,11 @@ export type InstalledPluginListResponse = {
|
||||
plugins: PluginDetail[]
|
||||
}
|
||||
|
||||
export type InstalledPluginListWithTotalResponse = {
|
||||
plugins: PluginDetail[]
|
||||
total: number
|
||||
}
|
||||
|
||||
export type InstalledLatestVersionResponse = {
|
||||
versions: {
|
||||
[plugin_id: string]: {
|
||||
|
||||
@ -11,6 +11,7 @@ import type {
|
||||
InstallPackageResponse,
|
||||
InstalledLatestVersionResponse,
|
||||
InstalledPluginListResponse,
|
||||
InstalledPluginListWithTotalResponse,
|
||||
PackageDependency,
|
||||
Permissions,
|
||||
Plugin,
|
||||
@ -33,6 +34,7 @@ import type {
|
||||
import { get, getMarketplace, post, postMarketplace } from './base'
|
||||
import type { MutateOptions, QueryOptions } from '@tanstack/react-query'
|
||||
import {
|
||||
useInfiniteQuery,
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
@ -74,6 +76,53 @@ export const useInstalledPluginList = (disable?: boolean) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const useInstalledPluginListWithPagination = (pageSize = 100) => {
|
||||
const fetchPlugins = async ({ pageParam = 1 }) => {
|
||||
const response = await get<InstalledPluginListWithTotalResponse>(
|
||||
`/workspaces/current/plugin/list?page=${pageParam}&page_size=${pageSize}`,
|
||||
)
|
||||
return response
|
||||
}
|
||||
|
||||
const {
|
||||
data,
|
||||
error,
|
||||
fetchNextPage,
|
||||
hasNextPage,
|
||||
isFetchingNextPage,
|
||||
isLoading,
|
||||
} = useInfiniteQuery({
|
||||
queryKey: ['installed-plugins', pageSize],
|
||||
queryFn: fetchPlugins,
|
||||
getNextPageParam: (lastPage, pages) => {
|
||||
const totalItems = lastPage.total
|
||||
const currentPage = pages.length
|
||||
const itemsLoaded = currentPage * pageSize
|
||||
|
||||
if (itemsLoaded >= totalItems)
|
||||
return
|
||||
|
||||
return currentPage + 1
|
||||
},
|
||||
initialPageParam: 1,
|
||||
})
|
||||
|
||||
const plugins = data?.pages.flatMap(page => page.plugins) ?? []
|
||||
|
||||
return {
|
||||
data: {
|
||||
plugins,
|
||||
},
|
||||
isLastPage: !hasNextPage,
|
||||
loadNextPage: () => {
|
||||
fetchNextPage()
|
||||
},
|
||||
isLoading,
|
||||
isFetching: isFetchingNextPage,
|
||||
error,
|
||||
}
|
||||
}
|
||||
|
||||
export const useInstalledLatestVersion = (pluginIds: string[]) => {
|
||||
return useQuery<InstalledLatestVersionResponse>({
|
||||
queryKey: [NAME_SPACE, 'installedLatestVersion', pluginIds],
|
||||
|
||||
Reference in New Issue
Block a user