Просмотр исходного кода

feat: implement mongoose-paginate-v2

https://youtrack.weseek.co.jp/issue/GW-7758
- Add nextPage props to InfiniteScroll Component
- Modify isReachingEnd function
- Collect swr data from response in RecentChanges
-Modify paging results interface
- Add custom label in pagination options
- Modify offset value in pages api
- Change return type of swr infinite response to paging result
I Komang Mudana 4 лет назад
Родитель
Сommit
715838b323

+ 9 - 9
packages/app/src/components/Sidebar/InfiniteScroll.tsx

@@ -3,11 +3,12 @@ import type { SWRInfiniteResponse } from 'swr/infinite';
 
 type Props<T> = {
   swr: SWRInfiniteResponse<T>
-  children:any,
+  children: React.ReactChild | ((item: T) => React.ReactNode),
   loadingIndicator?: React.ReactNode
   endingIndicator?: React.ReactNode
   isReachingEnd?: boolean,
-  offset?: number
+  offset?: number,
+  nextPage: number
 }
 
 const useIntersection = <T extends HTMLElement>(): [boolean, Ref<T>] => {
@@ -33,24 +34,23 @@ const InfiniteScroll = <T, >(props: Props<T>): React.ReactElement<Props<T>> => {
     endingIndicator,
     isReachingEnd,
     offset = 0,
+    nextPage,
   } = props;
 
+  const ending = isReachingEnd;
   const [intersecting, ref] = useIntersection<HTMLDivElement>();
-
-  // const ending = typeof isReachingEnd === 'function' ? isReachingEnd(swr) : isReachingEnd;
-
   useEffect(() => {
-    if (intersecting && !isValidating && !isReachingEnd) {
-      setSize(size => size + 1);
+    if (intersecting && !isValidating && !ending) {
+      setSize(nextPage);
     }
-  }, [intersecting, isValidating, setSize, isReachingEnd]);
+  }, [intersecting, isValidating, setSize, ending, nextPage]);
 
   return (
     <>
       {typeof children === 'function' ? data?.map(item => children(item)) : children}
       <div style={{ position: 'relative' }}>
         <div ref={ref} style={{ position: 'absolute', top: offset }}></div>
-        {isReachingEnd ? endingIndicator : loadingIndicator}
+        {ending ? endingIndicator : loadingIndicator}
       </div>
     </>
   );

+ 4 - 3
packages/app/src/components/Sidebar/RecentChanges.tsx

@@ -134,8 +134,8 @@ const RecentChanges = (): JSX.Element => {
   const { t } = useTranslation();
   const swr = useSWRInifinitexRecentlyUpdated();
   const [isRecentChangesSidebarSmall, setIsRecentChangesSidebarSmall] = useState(false);
-  const isReachingEnd = swr.data && swr.data[swr.data.length - 1]?.length < PER_PAGE;
-  const pages = swr.data?.flat()?.filter((item, index) => index === swr.data?.flat().findIndex(page => page._id === item._id));
+  const isReachingEnd = !swr.data?.[0].hasNextPage;
+  const nextPage = swr.data?.[0].nextPage ?? 1;
 
   const retrieveSizePreferenceFromLocalStorage = useCallback(() => {
     if (window.localStorage.isRecentChangesSidebarSmall === 'true') {
@@ -180,8 +180,9 @@ const RecentChanges = (): JSX.Element => {
             swr={swr}
             loadingIndicator={<LoadingIndicator />}
             isReachingEnd={isReachingEnd}
+            nextPage={nextPage}
           >
-            {pages?.map(page => (
+            {response => response?.items.map(page => (
               isRecentChangesSidebarSmall
                 ? <SmallPageItem key={page._id} page={page} />
                 : <LargePageItem key={page._id} page={page} />

+ 3 - 0
packages/app/src/interfaces/paging-result.ts

@@ -2,4 +2,7 @@ export type IPagingResult<T> = {
   items: T[],
   totalCount: number,
   limit: number,
+  nextPage?: number,
+  prevPage?: number,
+  hasNextPage?: boolean
 }

+ 16 - 7
packages/app/src/server/models/obsolete-page.js

@@ -525,16 +525,25 @@ export const getPageSchema = (crowi) => {
     // find
     // builder.addConditionToPagenate(opt.offset, opt.limit, sortOpt);
 
-
+    const customLabels = {
+      totalDocs: 'totalCount',
+      docs: 'pages',
+      limit: 'limit',
+      page: 'currentPage',
+      nextPage: 'nextPage',
+      prevPage: 'prevPage',
+      totalPages: 'pageCount',
+    };
     const paginationOptions = {
-      lean: true, limit: opt.limit, offset: opt.offset, page: opt.page,
+      lean: true, limit: opt.limit, offset: opt.offset, page: opt.page, customLabels,
     };
     builder.populateDataToList(User.USER_FIELDS_EXCEPT_CONFIDENTIAL);
-    const pages = await Page.paginate(builder, paginationOptions);
-    const results = {
-      pages: pages.docs, totalCount: pages.totalDocs, offset: opt.offset, limit: opt.limit,
-    };
-    return results;
+    const pages = await Page.paginate(builder.query, paginationOptions);
+    // const results = {
+    //   pages: pages.docs, totalCount: pages.totalDocs, offset: opt.offset, limit: opt.limit,
+    // };
+    console.log(pages);
+    return pages;
   }
 
   /**

+ 2 - 2
packages/app/src/server/routes/apiv3/pages.js

@@ -367,9 +367,9 @@ module.exports = (crowi) => {
     const limit = 20;
     const offset = parseInt(req.query.offset) || 0;
     const page = parseInt(req.query.page) || 1;
-
+    const skip = (+page - 1) * limit;
     const queryOptions = {
-      offset,
+      offset: skip,
       limit,
       includeTrashed: false,
       isRegExpEscapedFromPath: true,

+ 13 - 4
packages/app/src/stores/page.tsx

@@ -34,14 +34,23 @@ export const useSWRxRecentlyUpdated = (): SWRResponse<(IPageHasId)[], Error> =>
     endpoint => apiv3Get<{ pages:(IPageHasId)[] }>(endpoint).then(response => response.data?.pages),
   );
 };
-export const useSWRInifinitexRecentlyUpdated = () : SWRInfiniteResponse<(IPageHasId)[], Error> => {
-  const getKey = (offset: number, previousData: any) => {
+export const useSWRInifinitexRecentlyUpdated = () : SWRInfiniteResponse<IPagingResult<IPageHasId>, Error> => {
+  const getKey = (page: number, previousData: any) => {
     if (previousData && !previousData.length) return null;
-    return `/pages/recent?offset=${offset}`;
+    return `/pages/recent?page=${page + 1}`;
   };
   return useSWRInfinite(
     getKey,
-    (endpoint: string) => apiv3Get<{ pages:(IPageHasId)[] }>(endpoint).then(response => response.data?.pages),
+    (endpoint: string) => apiv3Get<{
+      pages: IPageHasId[], totalCount: number, limit: number, hasNextPage: boolean, nextPage: number}>(endpoint).then((response) => {
+        return {
+          items: response.data.pages,
+          totalCount: response.data.totalCount,
+          limit: response.data.limit,
+          hasNextPage: response.data.hasNextPage,
+          nextPage: response.data.nextPage,
+        };
+      }),
     {
       initialSize: 1,
       revalidateFirstPage: false,