mirror of
https://github.com/langgenius/dify.git
synced 2026-05-09 21:28:25 +08:00
feat(web): add infinite scroll to workflow run history panel
This commit is contained in:
parent
1873b22e96
commit
35e930ae5b
@ -117,8 +117,11 @@ describe('ViewHistory', () => {
|
||||
vi.clearAllMocks()
|
||||
mockIsChatMode = false
|
||||
mockUseWorkflowRunHistory.mockReturnValue({
|
||||
data: { data: [] } satisfies WorkflowRunHistoryResponse,
|
||||
data: { pages: [{ data: [], has_more: false, limit: 20 }] satisfies WorkflowRunHistoryResponse[] },
|
||||
isLoading: false,
|
||||
hasNextPage: false,
|
||||
isFetchingNextPage: false,
|
||||
fetchNextPage: vi.fn(),
|
||||
})
|
||||
})
|
||||
|
||||
@ -142,8 +145,11 @@ describe('ViewHistory', () => {
|
||||
it('renders the icon trigger variant and loading state, and clears log modals on trigger click', () => {
|
||||
const onClearLogAndMessageModal = vi.fn()
|
||||
mockUseWorkflowRunHistory.mockReturnValue({
|
||||
data: { data: [] } satisfies WorkflowRunHistoryResponse,
|
||||
data: { pages: [{ data: [], has_more: false, limit: 20 }] satisfies WorkflowRunHistoryResponse[] },
|
||||
isLoading: true,
|
||||
hasNextPage: false,
|
||||
isFetchingNextPage: false,
|
||||
fetchNextPage: vi.fn(),
|
||||
})
|
||||
|
||||
renderWorkflowComponent(
|
||||
@ -187,9 +193,12 @@ describe('ViewHistory', () => {
|
||||
|
||||
mockUseWorkflowRunHistory.mockReturnValue({
|
||||
data: {
|
||||
data: [pausedRun, failedRun, succeededRun],
|
||||
} satisfies WorkflowRunHistoryResponse,
|
||||
pages: [{ data: [pausedRun, failedRun, succeededRun], has_more: false, limit: 20 }] satisfies WorkflowRunHistoryResponse[],
|
||||
},
|
||||
isLoading: false,
|
||||
hasNextPage: false,
|
||||
isFetchingNextPage: false,
|
||||
fetchNextPage: vi.fn(),
|
||||
})
|
||||
|
||||
const { store } = renderWorkflowComponent(<ViewHistory historyUrl="/history" withText />, {
|
||||
@ -231,9 +240,12 @@ describe('ViewHistory', () => {
|
||||
|
||||
mockUseWorkflowRunHistory.mockReturnValue({
|
||||
data: {
|
||||
data: [chatRun],
|
||||
} satisfies WorkflowRunHistoryResponse,
|
||||
pages: [{ data: [chatRun], has_more: false, limit: 20 }] satisfies WorkflowRunHistoryResponse[],
|
||||
},
|
||||
isLoading: false,
|
||||
hasNextPage: false,
|
||||
isFetchingNextPage: false,
|
||||
fetchNextPage: vi.fn(),
|
||||
})
|
||||
|
||||
renderWorkflowComponent(<ViewHistory historyUrl="/history" withText />, {
|
||||
@ -250,8 +262,11 @@ describe('ViewHistory', () => {
|
||||
it('closes the popup from the close button and clears log modals', () => {
|
||||
const onClearLogAndMessageModal = vi.fn()
|
||||
mockUseWorkflowRunHistory.mockReturnValue({
|
||||
data: { data: [] } satisfies WorkflowRunHistoryResponse,
|
||||
data: { pages: [{ data: [], has_more: false, limit: 20 }] satisfies WorkflowRunHistoryResponse[] },
|
||||
isLoading: false,
|
||||
hasNextPage: false,
|
||||
isFetchingNextPage: false,
|
||||
fetchNextPage: vi.fn(),
|
||||
})
|
||||
|
||||
renderWorkflowComponent(
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import {
|
||||
memo,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -57,8 +59,26 @@ const ViewHistory = ({
|
||||
const {
|
||||
data,
|
||||
isLoading,
|
||||
hasNextPage,
|
||||
isFetchingNextPage,
|
||||
fetchNextPage,
|
||||
} = useWorkflowRunHistory(historyUrl, shouldFetchHistory)
|
||||
|
||||
const sentinelRef = useRef<HTMLDivElement>(null)
|
||||
useEffect(() => {
|
||||
const el = sentinelRef.current
|
||||
if (!el)
|
||||
return
|
||||
const observer = new IntersectionObserver(([entry]) => {
|
||||
if (entry.isIntersecting && hasNextPage && !isFetchingNextPage)
|
||||
fetchNextPage()
|
||||
})
|
||||
observer.observe(el)
|
||||
return () => observer.disconnect()
|
||||
}, [fetchNextPage, hasNextPage, isFetchingNextPage])
|
||||
|
||||
const allRuns = data?.pages.flatMap(page => page.data) ?? []
|
||||
|
||||
return (
|
||||
(
|
||||
<PortalToFollowElem
|
||||
@ -113,7 +133,7 @@ const ViewHistory = ({
|
||||
maxHeight: 'calc(2 / 3 * 100vh)',
|
||||
}}
|
||||
>
|
||||
<div className="sticky top-0 flex items-center justify-between bg-components-panel-bg px-4 pt-3 text-base font-semibold text-text-primary">
|
||||
<div className="sticky top-0 z-10 flex items-center justify-between bg-components-panel-bg px-4 pt-3 text-base font-semibold text-text-primary">
|
||||
<div className="grow">{t('common.runHistory', { ns: 'workflow' })}</div>
|
||||
<button
|
||||
type="button"
|
||||
@ -138,7 +158,7 @@ const ViewHistory = ({
|
||||
!isLoading && (
|
||||
<div className="p-2">
|
||||
{
|
||||
!data?.data.length && (
|
||||
!allRuns.length && (
|
||||
<div className="py-12">
|
||||
<span className="i-custom-vender-line-time-clock-play-slim mx-auto mb-2 h-8 w-8 text-text-quaternary" />
|
||||
<div className="text-center text-[13px] text-text-quaternary">
|
||||
@ -148,7 +168,7 @@ const ViewHistory = ({
|
||||
)
|
||||
}
|
||||
{
|
||||
data?.data.map(item => (
|
||||
allRuns.map(item => (
|
||||
<div
|
||||
key={item.id}
|
||||
className={cn(
|
||||
@ -203,6 +223,11 @@ const ViewHistory = ({
|
||||
</div>
|
||||
))
|
||||
}
|
||||
{hasNextPage && (
|
||||
<div ref={sentinelRef} className="flex h-8 items-center justify-center">
|
||||
{isFetchingNextPage && <Loading />}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -27,13 +27,25 @@ export const useAppWorkflow = (appID: string) => {
|
||||
}
|
||||
|
||||
const WorkflowRunHistoryKey = [NAME_SPACE, 'runHistory']
|
||||
const WORKFLOW_RUN_HISTORY_LIMIT = 20
|
||||
|
||||
export const useWorkflowRunHistory = (url?: string, enabled = true) => {
|
||||
return useQuery<WorkflowRunHistoryResponse>({
|
||||
return useInfiniteQuery<WorkflowRunHistoryResponse>({
|
||||
queryKey: [...WorkflowRunHistoryKey, url],
|
||||
queryFn: () => get<WorkflowRunHistoryResponse>(url as string),
|
||||
queryFn: ({ pageParam }) => get<WorkflowRunHistoryResponse>(url as string, {
|
||||
params: {
|
||||
limit: WORKFLOW_RUN_HISTORY_LIMIT,
|
||||
...(pageParam ? { last_id: pageParam } : {}),
|
||||
},
|
||||
}),
|
||||
enabled: !!url && enabled,
|
||||
staleTime: 0,
|
||||
initialPageParam: undefined as string | undefined,
|
||||
getNextPageParam: (lastPage) => {
|
||||
if (!lastPage.has_more || !lastPage.data.length)
|
||||
return undefined
|
||||
return lastPage.data[lastPage.data.length - 1].id
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -400,10 +400,8 @@ export type WorkflowRunHistory = {
|
||||
}
|
||||
export type WorkflowRunHistoryResponse = {
|
||||
data: WorkflowRunHistory[]
|
||||
}
|
||||
|
||||
export type ChatRunHistoryResponse = {
|
||||
data: WorkflowRunHistory[]
|
||||
has_more: boolean
|
||||
limit: number
|
||||
}
|
||||
|
||||
export type NodesDefaultConfigsResponse = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user