diff --git a/web/app/components/app/app-access-control/add-member-or-group-pop.tsx b/web/app/components/app/app-access-control/add-member-or-group-pop.tsx index 9c061d395e..59a0a055d3 100644 --- a/web/app/components/app/app-access-control/add-member-or-group-pop.tsx +++ b/web/app/components/app/app-access-control/add-member-or-group-pop.tsx @@ -19,27 +19,26 @@ export default function AddMemberOrGroupDialog() { const { t } = useTranslation() const [open, setOpen] = useState(false) const [keyword, setKeyword] = useState('') - const [pageNumber, setPageNumber] = useState(1) const debouncedKeyword = useDebounce(keyword, { wait: 500 }) - const { isPending, data } = useSearchForWhiteListCandidates({ keyword: debouncedKeyword, pageNumber, resultsPerPage: 10 }, open) + const { isPending, isFetchingNextPage, fetchNextPage, data } = useSearchForWhiteListCandidates({ keyword: debouncedKeyword, resultsPerPage: 10 }, open) const handleKeywordChange = (e: React.ChangeEvent) => { setKeyword(e.target.value) } const anchorRef = useRef(null) useEffect(() => { - const hasMore = data?.has_more ?? true + const hasMore = data?.pages?.[0].hasMore ?? false let observer: IntersectionObserver | undefined if (anchorRef.current) { observer = new IntersectionObserver((entries) => { if (entries[0].isIntersecting && !isPending && hasMore) - setPageNumber((size: number) => size + 1) + fetchNextPage() }, { rootMargin: '20px' }) observer.observe(anchorRef.current) } return () => observer?.disconnect() - }, [isPending, setPageNumber, anchorRef, data]) + }, [isPending, fetchNextPage, anchorRef, data]) return @@ -54,40 +53,37 @@ export default function AddMemberOrGroupDialog() { { - (data?.subjects?.length ?? 0) > 0 - ? <> -
- {t('app.accessControlDialog.operateGroupAndMember.allMembers')} -
- -
- - : isPending - ? null + isPending + ?
+ : (data?.pages?.length ?? 0) > 0 + ? <> +
+ {t('app.accessControlDialog.operateGroupAndMember.allMembers')} +
+ {renderGroupOrMember(data?.pages ?? [])} + {isFetchingNextPage &&
} +
+ :
{t('app.accessControlDialog.operateGroupAndMember.noResult')}
} - { - isPending &&
- }
} -type RenderGroupOrMemberProps = { - data: Subject[] -} - -function RenderGroupOrMember({ data }: RenderGroupOrMemberProps) { - return
- {data.map((item, index) => { - if (item.subjectType === SubjectType.Group) - return - return - })} -
+type GroupOrMemberData = { subjects: Subject[]; currPage: number }[] +function renderGroupOrMember(data: GroupOrMemberData) { + return data?.map((page) => { + return
+ {page.subjects?.map((item, index) => { + if (item.subjectType === SubjectType.Group) + return + return + })} +
+ }) ?? null } type GroupItemProps = { diff --git a/web/service/access-control.ts b/web/service/access-control.ts index 48673d0cdd..549ba43d7b 100644 --- a/web/service/access-control.ts +++ b/web/service/access-control.ts @@ -1,4 +1,4 @@ -import { useMutation, useQuery } from '@tanstack/react-query' +import { useInfiniteQuery, useMutation, useQuery } from '@tanstack/react-query' import { get, post } from './base' import type { AccessControlAccount, AccessControlGroup, Subject } from '@/models/access-control' import type { App } from '@/types/app' @@ -17,21 +17,28 @@ type SearchResults = { currPage: number totalPages: number subjects: Subject[] - has_more: boolean + hasMore: boolean } -export const useSearchForWhiteListCandidates = (query: { appId?: string; keyword?: string; pageNumber?: number; resultsPerPage?: number }, enabled: boolean) => { - return useQuery({ +export const useSearchForWhiteListCandidates = (query: { keyword?: string; resultsPerPage?: number }, enabled: boolean) => { + return useInfiniteQuery({ queryKey: [NAME_SPACE, 'app-whitelist-candidates', query], - queryFn: () => { + queryFn: ({ pageParam }) => { const params = new URLSearchParams() Object.keys(query).forEach((key) => { const typedKey = key as keyof typeof query if (query[typedKey]) params.append(key, `${query[typedKey]}`) }) + params.append('pageNumber', `${pageParam}`) return get(`/enterprise/webapp/app/subject/search?${new URLSearchParams(params).toString()}`) }, + initialPageParam: 1, + getNextPageParam: (lastPage) => { + if (lastPage.hasMore) + return lastPage.currPage + 1 + return undefined + }, enabled, }) }