diff --git a/src/routes/ins/$insID/_layout/tasks.tsx b/src/routes/ins/$insID/_layout/tasks.tsx index 68bc957..ad54c32 100644 --- a/src/routes/ins/$insID/_layout/tasks.tsx +++ b/src/routes/ins/$insID/_layout/tasks.tsx @@ -7,11 +7,11 @@ import { getDuration } from '@/utils/text'; import { Modal, Select, Table, TagInput } from '@douyinfe/semi-ui'; import { ColumnProps } from '@douyinfe/semi-ui/lib/es/table'; import { Button } from '@nextui-org/react'; -import { useQuery } from '@tanstack/react-query'; +import { useInfiniteQuery } from '@tanstack/react-query'; import { createFileRoute, Link, useNavigate } from '@tanstack/react-router'; import _ from 'lodash'; import { TasksQuery, Task, TaskTypes, TaskStatus } from 'meilisearch'; -import { useEffect, useReducer } from 'react'; +import { useEffect, useMemo, useReducer } from 'react'; import { useTranslation } from 'react-i18next'; import ReactJson from 'react-json-view'; import { z } from 'zod'; @@ -19,8 +19,7 @@ import { z } from 'zod'; const searchSchema = z .object({ indexUids: z.string().array().optional(), - limit: z.number().positive().optional(), - from: z.number().nonnegative().optional(), + limit: z.number().positive().optional().default(20), statuses: z.string().array().optional(), types: z.string().array().optional(), }) @@ -53,15 +52,27 @@ const Page = () => { }); }, [navigate, state]); - const query = useQuery({ + // @ts-expect-error + const query = useInfiniteQuery({ queryKey: ['tasks', host, state], - queryFn: async () => { + queryFn: async ({ pageParam }: { pageParam: { limit: number; from?: number } }) => { showRequestLoader(); console.debug('getTasks', client.config, state); return await client.getTasks({ ..._.omitBy(state, _.isEmpty), + from: pageParam.from, + limit: pageParam.limit, }); }, + initialPageParam: { + limit: state.limit, + }, + getNextPageParam: (lastPage) => { + return { + limit: lastPage.limit, + from: lastPage.next, + }; + }, }); useEffect(() => { @@ -73,142 +84,162 @@ const Page = () => { } }, [query.error, query.isError, query.isFetching]); - const columns: ColumnProps[] = [ - { - title: 'UID', - dataIndex: 'uid', - width: 100, - }, - { - title: t('indexes'), - dataIndex: 'indexUid', - render: (val) => (val ? {val} : '-'), - }, - { - title: t('common:type'), - dataIndex: 'type', - render: (_) => t(`type.${_}`), - }, - { - title: t('common:status'), - dataIndex: 'status', - width: 120, - render: (_) => t(`status.${_}`), - }, - { - title: t('duration'), - dataIndex: 'duration', - width: 200, - render: (_, item) => { - if (!item.duration) { - return '-'; - } + const list = useMemo(() => { + return query.data?.pages.map((page) => page.results).reduce((acc, cur) => acc.concat(cur), []) || []; + }, [query.data?.pages]); - return `${getDuration(item.duration, 'millisecond')}ms`; + const columns: ColumnProps[] = useMemo( + () => [ + { + title: 'UID', + dataIndex: 'uid', + width: 100, }, - }, - { - title: t('enqueued_at'), - dataIndex: 'enqueuedAt', - width: 220, - render: (_, item) => { - return ; + { + title: t('indexes'), + dataIndex: 'indexUid', + render: (val) => (val ? {val} : '-'), }, - }, - { - title: t('started_at'), - dataIndex: 'startedAt', - width: 220, - render: (_, item) => { - return ; + { + title: t('common:type'), + dataIndex: 'type', + render: (_) => t(`type.${_}`), }, - }, - { - title: t('finished_at'), - dataIndex: 'finishedAt', - width: 220, - render: (_, item) => { - return ; + { + title: t('common:status'), + dataIndex: 'status', + width: 120, + render: (_) => t(`status.${_}`), }, - }, - { - title: t('actions'), - fixed: 'right', - width: 150, - render: (_, record) => ( -
- -
- ), - }, - ]; + { + title: t('duration'), + dataIndex: 'duration', + width: 200, + render: (_, item) => { + if (!item.duration) { + return '-'; + } - return ( -
-
-
- { - updateState({ indexUids: value }); - }} - /> - ).map(([k, v]) => ({ - value: k, - label: v, - }))} - multiple - value={state.statuses} - onChange={(value) => { - updateState({ statuses: (value as TaskStatus[]) || undefined }); - }} - /> -
+ return `${getDuration(item.duration, 'millisecond')}ms`; + }, + }, + { + title: t('enqueued_at'), + dataIndex: 'enqueuedAt', + width: 220, + render: (_, item) => { + return ; + }, + }, + { + title: t('started_at'), + dataIndex: 'startedAt', + width: 220, + render: (_, item) => { + return ; + }, + }, + { + title: t('finished_at'), + dataIndex: 'finishedAt', + width: 220, + render: (_, item) => { + return ; + }, + }, + { + title: t('actions'), + fixed: 'right', + width: 150, + render: (_, record) => ( +
+ +
+ ), + }, + ], + [currentInstance.id, t] + ); - - - + return useMemo( + () => ( +
+
+
+ { + updateState({ indexUids: value }); + }} + /> + ).map(([k, v]) => ({ + value: k, + label: v, + }))} + multiple + value={state.statuses} + onChange={(value) => { + updateState({ statuses: (value as TaskStatus[]) || undefined }); + }} + /> +
+ +
{ + const { scrollTop, clientHeight, scrollHeight } = e.target; + if (Math.abs(scrollHeight - (scrollTop + clientHeight)) <= 1) { + query.fetchNextPage(); + } + }} + > +
+ + + + ), + [t, state.indexUids, state.types, state.statuses, columns, list, query] ); };