Преглед изворни кода

WIP: retrieve PageInfoForList from API

Yuki Takei пре 4 година
родитељ
комит
39d8344527

+ 14 - 3
packages/app/src/components/IdenticalPathPage.tsx

@@ -8,6 +8,7 @@ import { DevidedPagePath } from '@growi/core';
 import { useCurrentPagePath } from '~/stores/context';
 import { useCurrentPagePath } from '~/stores/context';
 
 
 import { PageListItemL } from './PageList/PageListItemL';
 import { PageListItemL } from './PageList/PageListItemL';
+import { useSWRxPageInfoForList } from '~/stores/page';
 
 
 
 
 type IdenticalPathAlertProps = {
 type IdenticalPathAlertProps = {
@@ -56,7 +57,10 @@ const IdenticalPathPage:FC<IdenticalPathPageProps> = (props: IdenticalPathPagePr
 
 
   const identicalPageDocument = document.getElementById('identical-path-page');
   const identicalPageDocument = document.getElementById('identical-path-page');
   const pageDataList = JSON.parse(identicalPageDocument?.getAttribute('data-identical-page-data-list') || jsonNull);
   const pageDataList = JSON.parse(identicalPageDocument?.getAttribute('data-identical-page-data-list') || jsonNull);
-  const shortbodyMap = JSON.parse(identicalPageDocument?.getAttribute('data-shortody-map') || jsonNull);
+
+  const pageIds = pageDataList.map(data => data.pageData._id) as string[];
+
+  const { data: idToPageInfoMap } = useSWRxPageInfoForList(pageIds);
 
 
   const { data: currentPath } = useCurrentPagePath();
   const { data: currentPath } = useCurrentPagePath();
 
 
@@ -78,14 +82,21 @@ const IdenticalPathPage:FC<IdenticalPathPageProps> = (props: IdenticalPathPagePr
         <div className="page-list">
         <div className="page-list">
           <ul className="page-list-ul list-group-flush border px-3">
           <ul className="page-list-ul list-group-flush border px-3">
             {pageDataList.map((data) => {
             {pageDataList.map((data) => {
+              const pageId = data.pageData._id;
+              const pageInfo = (idToPageInfoMap ?? {})[pageId];
+
+              const pageWithMeta = {
+                pageData: data.pageData,
+                pegeMeta: pageInfo,
+              };
+
               return (
               return (
                 <PageListItemL
                 <PageListItemL
                   key={data.pageData._id}
                   key={data.pageData._id}
-                  page={data}
+                  page={pageWithMeta}
                   isSelected={false}
                   isSelected={false}
                   isChecked={false}
                   isChecked={false}
                   isEnableActions
                   isEnableActions
-                  shortBody={shortbodyMap[data.pageData._id]}
                 // Todo: add onClickDeleteButton when delete feature implemented
                 // Todo: add onClickDeleteButton when delete feature implemented
                 />
                 />
               );
               );

+ 12 - 13
packages/app/src/components/PageList/PageListItemL.tsx

@@ -5,17 +5,16 @@ import Clamp from 'react-multiline-clamp';
 import { UserPicture, PageListMeta, PagePathLabel } from '@growi/ui';
 import { UserPicture, PageListMeta, PagePathLabel } from '@growi/ui';
 import { DevidedPagePath } from '@growi/core';
 import { DevidedPagePath } from '@growi/core';
 import { useIsDeviceSmallerThanLg } from '~/stores/ui';
 import { useIsDeviceSmallerThanLg } from '~/stores/ui';
-import { IPageWithMeta } from '~/interfaces/page';
+import { IPageInfoForList, IPageWithMeta, isIPageInfoForList } from '~/interfaces/page';
 import { IPageSearchMeta, isIPageSearchMeta } from '~/interfaces/search';
 import { IPageSearchMeta, isIPageSearchMeta } from '~/interfaces/search';
 
 
 import { AsyncPageItemControl } from '../Common/Dropdown/PageItemControl';
 import { AsyncPageItemControl } from '../Common/Dropdown/PageItemControl';
 
 
 type Props = {
 type Props = {
-  page: IPageWithMeta | IPageWithMeta<IPageSearchMeta>,
+  page: IPageWithMeta | IPageWithMeta<IPageSearchMeta> | IPageWithMeta<IPageInfoForList>,
   isSelected?: boolean, // is item selected(focused)
   isSelected?: boolean, // is item selected(focused)
   isChecked?: boolean, // is checkbox of item checked
   isChecked?: boolean, // is checkbox of item checked
   isEnableActions?: boolean,
   isEnableActions?: boolean,
-  shortBody?: string
   showPageUpdatedTime?: boolean, // whether to show page's updated time at the top-right corner of item
   showPageUpdatedTime?: boolean, // whether to show page's updated time at the top-right corner of item
   onClickCheckbox?: (pageId: string) => void,
   onClickCheckbox?: (pageId: string) => void,
   onClickItem?: (pageId: string) => void,
   onClickItem?: (pageId: string) => void,
@@ -25,7 +24,7 @@ type Props = {
 export const PageListItemL: FC<Props> = memo((props:Props) => {
 export const PageListItemL: FC<Props> = memo((props:Props) => {
   const {
   const {
     // todo: refactoring variable name to clear what changed
     // todo: refactoring variable name to clear what changed
-    page: { pageData, pageMeta }, isSelected, onClickItem, onClickCheckbox, isChecked, isEnableActions, shortBody,
+    page: { pageData, pageMeta }, isSelected, onClickItem, onClickCheckbox, isChecked, isEnableActions,
     showPageUpdatedTime,
     showPageUpdatedTime,
   } = props;
   } = props;
 
 
@@ -34,6 +33,7 @@ export const PageListItemL: FC<Props> = memo((props:Props) => {
   const pagePath: DevidedPagePath = new DevidedPagePath(pageData.path, true);
   const pagePath: DevidedPagePath = new DevidedPagePath(pageData.path, true);
 
 
   const elasticSearchResult = isIPageSearchMeta(pageMeta) ? pageMeta.elasticSearchResult : null;
   const elasticSearchResult = isIPageSearchMeta(pageMeta) ? pageMeta.elasticSearchResult : null;
+  const revisionShortBody = isIPageInfoForList(pageMeta) ? pageMeta.revisionShortBody : null;
 
 
   const pageTitle = (
   const pageTitle = (
     <PagePathLabel
     <PagePathLabel
@@ -103,7 +103,7 @@ export const PageListItemL: FC<Props> = memo((props:Props) => {
             <div className="d-flex align-items-center mb-2">
             <div className="d-flex align-items-center mb-2">
               {/* Picture */}
               {/* Picture */}
               <span className="mr-2 d-none d-md-block">
               <span className="mr-2 d-none d-md-block">
-                <UserPicture user={pageData.lastUpdateUser} size="md" />
+                {/* <UserPicture user={pageData.lastUpdateUser} size="md" /> */}
               </span>
               </span>
               {/* page title */}
               {/* page title */}
               <Clamp lines={1}>
               <Clamp lines={1}>
@@ -128,14 +128,13 @@ export const PageListItemL: FC<Props> = memo((props:Props) => {
             </div>
             </div>
             <div className="page-list-snippet py-1">
             <div className="page-list-snippet py-1">
               <Clamp lines={2}>
               <Clamp lines={2}>
-                {
-                  elasticSearchResult != null && elasticSearchResult?.snippet.length !== 0 ? (
-                    // eslint-disable-next-line react/no-danger
-                    <div dangerouslySetInnerHTML={{ __html: elasticSearchResult.snippet }}></div>
-                  ) : (
-                    <div>{ shortBody != null ? shortBody : 'Loading ...' }</div> // TODO: improve indicator
-                  )
-                }
+                { elasticSearchResult != null && elasticSearchResult?.snippet.length > 0 && (
+                  // eslint-disable-next-line react/no-danger
+                  <div dangerouslySetInnerHTML={{ __html: elasticSearchResult.snippet }}></div>
+                ) }
+                { revisionShortBody != null && (
+                  <div>{revisionShortBody}</div>
+                ) }
               </Clamp>
               </Clamp>
             </div>
             </div>
           </div>
           </div>

+ 6 - 1
packages/app/src/interfaces/page.ts

@@ -57,10 +57,15 @@ export type IPageInfo = IPageInfoCommon & {
 
 
 export type IPageInfoForList = IPageInfo & HasRevisionShortbody;
 export type IPageInfoForList = IPageInfo & HasRevisionShortbody;
 
 
-export const isExistPageInfo = (pageInfo: IPageInfoCommon | IPageInfo | undefined): pageInfo is IPageInfo => {
+export const isExistPageInfo = (pageInfo: IPageInfoCommon | undefined): pageInfo is IPageInfo => {
   return pageInfo != null && !pageInfo.isEmpty;
   return pageInfo != null && !pageInfo.isEmpty;
 };
 };
 
 
+// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
+export const isIPageInfoForList = (pageInfo: any): pageInfo is IPageInfoForList => {
+  return pageInfo != null && pageInfo.revisionShortBody != null;
+};
+
 export type IPageWithMeta<M = Record<string, unknown>> = {
 export type IPageWithMeta<M = Record<string, unknown>> = {
   pageData: IPageHasId,
   pageData: IPageHasId,
   pageMeta?: Partial<IPageInfo> & M,
   pageMeta?: Partial<IPageInfo> & M,

+ 0 - 4
packages/app/src/server/routes/page.js

@@ -285,21 +285,17 @@ module.exports = function(crowi, app) {
 
 
   async function addRenderVarsForIdenticalPage(renderVars, pages) {
   async function addRenderVarsForIdenticalPage(renderVars, pages) {
     const pageIds = pages.map(p => p._id);
     const pageIds = pages.map(p => p._id);
-    const shortBodyMap = await crowi.pageService.shortBodiesMapByPageIds(pageIds);
 
 
     const identicalPageDataList = await Promise.all(pages.map(async(page) => {
     const identicalPageDataList = await Promise.all(pages.map(async(page) => {
-      const bookmarkCount = await Bookmark.countByPageId(page._id);
       page._doc.seenUserCount = (page.seenUsers && page.seenUsers.length) || 0;
       page._doc.seenUserCount = (page.seenUsers && page.seenUsers.length) || 0;
       return {
       return {
         pageData: page,
         pageData: page,
         pageMeta: {
         pageMeta: {
-          bookmarkCount,
         },
         },
       };
       };
     }));
     }));
 
 
     renderVars.identicalPageDataList = identicalPageDataList;
     renderVars.identicalPageDataList = identicalPageDataList;
-    renderVars.shortBodyMap = shortBodyMap;
   }
   }
 
 
   function replacePlaceholdersOfTemplate(template, req) {
   function replacePlaceholdersOfTemplate(template, req) {

+ 0 - 1
packages/app/src/server/views/layout-growi/identical-path-page.html

@@ -19,7 +19,6 @@
         <div
         <div
           id="identical-path-page"
           id="identical-path-page"
           data-identical-page-data-list="{{ identicalPageDataList|json }}"
           data-identical-page-data-list="{{ identicalPageDataList|json }}"
-          data-shortody-map="{{ shortBodyMap|json }}"
         ></div>
         ></div>
       </div>
       </div>
       <div id="page-context"></div>
       <div id="page-context"></div>

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

@@ -3,7 +3,9 @@ import useSWRImmutable from 'swr/immutable';
 
 
 import { apiv3Get } from '~/client/util/apiv3-client';
 import { apiv3Get } from '~/client/util/apiv3-client';
 
 
-import { IPageInfo, IPageInfoCommon, IPageHasId } from '~/interfaces/page';
+import {
+  IPageInfo, IPageInfoCommon, IPageInfoForList, IPageHasId,
+} from '~/interfaces/page';
 import { IPagingResult } from '~/interfaces/paging-result';
 import { IPagingResult } from '~/interfaces/paging-result';
 import { apiGet } from '../client/util/apiv1-client';
 import { apiGet } from '../client/util/apiv1-client';
 
 
@@ -63,3 +65,13 @@ export const useSWRxPageInfo = (pageId: string | null | undefined): SWRResponse<
     (endpoint, pageId) => apiv3Get(endpoint, { pageId }).then(response => response.data),
     (endpoint, pageId) => apiv3Get(endpoint, { pageId }).then(response => response.data),
   );
   );
 };
 };
+
+export const useSWRxPageInfoForList = (pageIds: string[] | null | undefined): SWRResponse<Record<string, IPageInfoCommon|IPageInfoForList>, Error> => {
+
+  const shouldFetch = pageIds != null && pageIds.length > 0;
+
+  return useSWRImmutable(
+    shouldFetch ? ['/page-listing/info', pageIds] : null,
+    (endpoint, pageIds) => apiv3Get(endpoint, { pageIds }).then(response => response.data),
+  );
+};