jam411 3 лет назад
Родитель
Сommit
abb17ea8c5

+ 5 - 10
packages/app/src/components/Page.tsx

@@ -13,12 +13,12 @@ import { HtmlElementNode } from 'rehype-toc';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import { getOptionsToSave } from '~/client/util/editor';
 import {
-  useIsGuestUser, useShareLinkId, useIsLatestRevision,
+  useIsGuestUser, useShareLinkId, useCurrentRevisionId,
 } from '~/stores/context';
 import {
   useSWRxSlackChannels, useIsSlackEnabled, usePageTagsForEditors, useIsEnabledUnsavedWarning,
 } from '~/stores/editor';
-import { useSWRxCurrentPage, useRequestRevisionPage } from '~/stores/page';
+import { useSWRxCurrentPage } from '~/stores/page';
 import { useViewOptions } from '~/stores/renderer';
 import {
   useCurrentPageTocNode,
@@ -212,8 +212,9 @@ export const Page = (props) => {
     tocRef.current = toc;
   }, []);
 
+  const { data: revisionId } = useCurrentRevisionId();
   const { data: shareLinkId } = useShareLinkId();
-  const { data: currentPage } = useSWRxCurrentPage(shareLinkId ?? undefined);
+  const { data: currentPage } = useSWRxCurrentPage(shareLinkId ?? undefined, revisionId ?? undefined);
   const { data: editorMode } = useEditorMode();
   const { data: isGuestUser } = useIsGuestUser();
   const { data: isMobile } = useIsMobile();
@@ -224,10 +225,6 @@ export const Page = (props) => {
   const { mutate: mutateIsEnabledUnsavedWarning } = useIsEnabledUnsavedWarning();
   const { mutate: mutateCurrentPageTocNode } = useCurrentPageTocNode();
 
-  // for History "View this version" function on PageAccessoryModal
-  const { data: isLatestRevision } = useIsLatestRevision();
-  const { data: requestRevisionPage } = useRequestRevisionPage();
-
   const pageRef = useRef(null);
 
   useEffect(() => {
@@ -274,14 +271,12 @@ export const Page = (props) => {
     return null;
   }
 
-  const page = ((requestRevisionPage != null && isLatestRevision != null) && !isLatestRevision) ? requestRevisionPage : currentPage;
-
   return (
     <PageSubstance
       {...props}
       ref={pageRef}
       rendererOptions={rendererOptions}
-      page={page}
+      page={currentPage}
       editorMode={editorMode}
       isGuestUser={isGuestUser}
       isMobile={isMobile}

+ 2 - 2
packages/app/src/components/PageAccessoriesModal.tsx

@@ -57,7 +57,7 @@ const PageAccessoriesModal = (): JSX.Element => {
           if (!isOpened) {
             return <></>;
           }
-          return <PageHistory />;
+          return <PageHistory onCloseModal={close}/>;
         },
         i18n: t('History'),
         index: 0,
@@ -87,7 +87,7 @@ const PageAccessoriesModal = (): JSX.Element => {
         isLinkEnabled: () => !isGuestUser && !isSharedUser && !isLinkSharingDisabled,
       },
     };
-  }, [status, t, isGuestUser, isSharedUser, isLinkSharingDisabled]);
+  }, [status, t, close, isGuestUser, isSharedUser, isLinkSharingDisabled]);
 
   const buttons = useMemo(() => (
     <div className="d-flex flex-nowrap">

+ 2 - 2
packages/app/src/components/PageAlert/OldRevisionAlert.tsx

@@ -19,8 +19,8 @@ export const OldRevisionAlert = (): JSX.Element => {
   return (
     <div className="alert alert-warning">
       <strong>{ t('Warning') }: </strong> { t('page_page.notice.version') }
-      <Link href={`/${page._id}`}>
-        <a><i className="icon-fw icon-arrow-right-circle"></i>{ t('Show latest') }</a>
+      <Link href={`/${page._id}?revisionId=${page.revision._id}`}>
+        <a href={`/${page._id}`}><i className="icon-fw icon-arrow-right-circle"></i>{ t('Show latest') }</a>
       </Link>
     </div>
   );

+ 2 - 1
packages/app/src/components/PageHistory.tsx

@@ -12,7 +12,7 @@ import { RevisionComparer } from './RevisionComparer/RevisionComparer';
 
 const logger = loggerFactory('growi:PageHistory');
 
-export const PageHistory = (): JSX.Element => {
+export const PageHistory: React.FC<{ onCloseModal: () => void }> = ({ onCloseModal }) => {
 
   const [activePage, setActivePage] = useState(1);
 
@@ -65,6 +65,7 @@ export const PageHistory = (): JSX.Element => {
         targetRevision={targetRevision}
         onChangeSourceInvoked={setSourceRevision}
         onChangeTargetInvoked={setTargetRevision}
+        onCloseModal={onCloseModal}
       />
       <div className="my-3">
         {pager()}

+ 6 - 4
packages/app/src/components/PageHistory/PageRevisionTable.tsx

@@ -14,13 +14,14 @@ type PageRevisionTAble = {
   targetRevision: IRevisionHasId,
   onChangeSourceInvoked: React.Dispatch<React.SetStateAction<IRevisionHasId | undefined>>,
   onChangeTargetInvoked: React.Dispatch<React.SetStateAction<IRevisionHasId | undefined>>,
+  onCloseModal: () => void,
 }
 
 export const PageRevisionTable = (props: PageRevisionTAble): JSX.Element => {
   const { t } = useTranslation();
 
   const {
-    revisions, pagingLimit, sourceRevision, targetRevision, onChangeSourceInvoked, onChangeTargetInvoked,
+    revisions, pagingLimit, sourceRevision, targetRevision, onChangeSourceInvoked, onChangeTargetInvoked, onCloseModal,
   } = props;
 
   const revisionCount = revisions.length;
@@ -51,6 +52,7 @@ export const PageRevisionTable = (props: PageRevisionTAble): JSX.Element => {
               isLatestRevision={revision === latestRevision}
               hasDiff={hasDiff}
               key={`revision-history-rev-${revisionId}`}
+              onCloseModal={onCloseModal}
             />
             {hasDiff && (
               <div className="ml-md-3 mt-auto">
@@ -132,9 +134,9 @@ export const PageRevisionTable = (props: PageRevisionTAble): JSX.Element => {
     <table className={`${styles['revision-history-table']} table revision-history-table`}>
       <thead>
         <tr className="d-flex">
-          <th className="col">{ t('page_history.revision') }</th>
-          <th className="col-1">{ t('page_history.comparing_source') }</th>
-          <th className="col-2">{ t('page_history.comparing_target') }</th>
+          <th className="col">{t('page_history.revision')}</th>
+          <th className="col-1">{t('page_history.comparing_source')}</th>
+          <th className="col-2">{t('page_history.comparing_target')}</th>
         </tr>
       </thead>
       <tbody className="overflow-auto d-block">

+ 12 - 5
packages/app/src/components/PageHistory/Revision.tsx

@@ -3,22 +3,27 @@ import React from 'react';
 import { IRevisionHasId } from '@growi/core';
 import { UserPicture } from '@growi/ui';
 import { useTranslation } from 'next-i18next';
+import Link from 'next/link';
 
 import UserDate from '../User/UserDate';
 import { Username } from '../User/Username';
 
 import styles from './Revision.module.scss';
 
+
 type RevisionProps = {
   revision: IRevisionHasId,
   isLatestRevision: boolean,
   hasDiff: boolean,
+  onCloseModal: () => void,
 }
 
 export const Revision = (props: RevisionProps): JSX.Element => {
   const { t } = useTranslation();
 
-  const { revision, isLatestRevision, hasDiff } = props;
+  const {
+    revision, isLatestRevision, hasDiff, onCloseModal,
+  } = props;
 
   const renderSimplifiedNodiff = (revision: IRevisionHasId) => {
 
@@ -34,7 +39,7 @@ export const Revision = (props: RevisionProps): JSX.Element => {
         </div>
         <div className="ml-3">
           <span className="text-muted small">
-            <UserDate dateTime={revision.createdAt} /> ({ t('No diff') })
+            <UserDate dateTime={revision.createdAt} /> {t('No diff')}
           </span>
         </div>
       </div>
@@ -60,9 +65,11 @@ export const Revision = (props: RevisionProps): JSX.Element => {
           <div className="mb-1">
             <UserDate dateTime={revision.createdAt} />
             <br className="d-xl-none d-block" />
-            <a className="ml-xl-3" href={`?revisionId=${revision._id}`}>
-              <i className="icon-login"></i> { t('Go to this version') }
-            </a>
+            <Link href={`?revisionId=${revision._id}`} prefetch={false}>
+              <a className="ml-xl-3" onClick={onCloseModal}>
+                <i className="icon-login"></i> {t('Go to this version')}
+              </a>
+            </Link>
           </div>
         </div>
       </div>

+ 10 - 5
packages/app/src/pages/[[...path]].page.tsx

@@ -37,7 +37,7 @@ import type { PageModel, PageDocument } from '~/server/models/page';
 import type { PageRedirectModel } from '~/server/models/page-redirect';
 import type { UserUISettingsModel } from '~/server/models/user-ui-settings';
 import {
-  useSWRxCurrentPage, useSWRxIsGrantNormalized, useSWRxPageInfo, useRequestRevisionPage,
+  useSWRxCurrentPage, useSWRxIsGrantNormalized, useSWRxPageInfo,
 } from '~/stores/page';
 import { useRedirectFrom } from '~/stores/page-redirect';
 import {
@@ -59,7 +59,7 @@ import DisplaySwitcher from '../components/Page/DisplaySwitcher';
 // import PageStatusAlert from '../client/js/components/PageStatusAlert';
 import {
   useCurrentUser,
-  useIsLatestRevision,
+  useIsLatestRevision, useCurrentRevisionId,
   useIsForbidden, useIsNotFound, useIsSharedUser,
   useIsEnabledStaleNotification, useIsIdenticalPath,
   useIsSearchServiceConfigured, useIsSearchServiceReachable, useDisableLinkSharing,
@@ -136,7 +136,8 @@ type Props = CommonProps & {
   redirectFrom?: string;
 
   // shareLinkId?: string;
-  isLatestRevision?: boolean
+  isLatestRevision?: boolean,
+  revisionId?: string,
 
   isIdenticalPathPage?: boolean,
   isForbidden: boolean,
@@ -244,9 +245,9 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
   // useIsNotCreatable(props.isForbidden || !isCreatablePage(pagePath)); // TODO: need to include props.isIdentical
   useCurrentPathname(props.currentPathname);
 
-  const { data: currentPage } = useSWRxCurrentPage(undefined, pageWithMeta?.data ?? null); // store initial data
+  const { data: currentPage } = useSWRxCurrentPage(undefined, props.revisionId, pageWithMeta?.data ?? null); // store initial data
   useEditingMarkdown(pageWithMeta?.data.revision?.body ?? '');
-  useRequestRevisionPage(pageWithMeta?.data); // store request revisionId page data History function on PageAccessoryModal
+  useCurrentRevisionId(props.revisionId); // store request revisionId page data History function on PageAccessoryModal
 
   const { data: grantData } = useSWRxIsGrantNormalized(pageId);
   const { mutate: mutateSelectedGrant } = useSelectedGrant();
@@ -416,6 +417,10 @@ async function injectPageData(context: GetServerSidePropsContext, props: Props):
     props.isLatestRevision = page.isLatestRevision();
   }
 
+  if (typeof revisionId === 'string' || typeof revisionId === 'undefined') {
+    props.revisionId = revisionId;
+  }
+
   props.pageWithMeta = pageWithMeta;
 }
 

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

@@ -255,7 +255,9 @@ module.exports = (crowi) => {
    */
   router.get('/', certifySharedPage, accessTokenParser, loginRequired, validator.getPage, apiV3FormValidator, async(req, res) => {
     const { user } = req;
-    const { pageId, path, findAll } = req.query;
+    const {
+      pageId, path, findAll, revisionId,
+    } = req.query;
 
     if (pageId == null && path == null) {
       return res.apiv3Err(new ErrorV3('Either parameter of path or pageId is required.', 'invalid-request'));
@@ -285,7 +287,7 @@ module.exports = (crowi) => {
 
     if (page != null) {
       try {
-        page.initLatestRevisionField();
+        page.initLatestRevisionField(revisionId);
 
         // populate
         page = await page.populateDataToShowRevision();

+ 2 - 2
packages/app/src/stores/context.tsx

@@ -48,8 +48,8 @@ export const useCurrentUser = (initialData?: Nullable<IUser>): SWRResponse<Nulla
   return useContextSWR<Nullable<IUser>, Error>('currentUser', initialData);
 };
 
-export const useRevisionId = (initialData?: Nullable<any>): SWRResponse<Nullable<any>, Error> => {
-  return useContextSWR<Nullable<any>, Error>('revisionId', initialData);
+export const useCurrentRevisionId = (initialData?: string): SWRResponse<string, Error> => {
+  return useContextSWR('currentRevisionId', initialData);
 };
 
 export const useCurrentPathname = (initialData?: string): SWRResponse<string, Error> => {

+ 5 - 9
packages/app/src/stores/page.tsx

@@ -24,11 +24,12 @@ const { isPermalink: _isPermalink } = pagePathUtils;
 export const useSWRxPage = (
     pageId?: string|null,
     shareLinkId?: string,
+    revisionId?: string,
     initialData?: IPagePopulatedToShowRevision|null,
 ): SWRResponse<IPagePopulatedToShowRevision|null, Error> => {
   return useSWR<IPagePopulatedToShowRevision|null, Error>(
-    pageId != null ? ['/page', pageId, shareLinkId] : null,
-    (endpoint, pageId, shareLinkId) => apiv3Get<{ page: IPagePopulatedToShowRevision }>(endpoint, { pageId, shareLinkId })
+    pageId != null ? ['/page', pageId, shareLinkId, revisionId] : null,
+    (endpoint, pageId, shareLinkId, revisionId) => apiv3Get<{ page: IPagePopulatedToShowRevision }>(endpoint, { pageId, shareLinkId, revisionId })
       .then(result => result.data.page)
       .catch((errs) => {
         if (!Array.isArray(errs)) { throw Error('error is not array') }
@@ -51,11 +52,11 @@ export const useSWRxPageByPath = (path?: string): SWRResponse<IPagePopulatedToSh
 };
 
 export const useSWRxCurrentPage = (
-    shareLinkId?: string, initialData?: IPagePopulatedToShowRevision|null,
+    shareLinkId?: string, revisionId?: string, initialData?: IPagePopulatedToShowRevision|null,
 ): SWRResponse<IPagePopulatedToShowRevision|null, Error> => {
   const { data: currentPageId } = useCurrentPageId();
 
-  const swrResult = useSWRxPage(currentPageId, shareLinkId, initialData);
+  const swrResult = useSWRxPage(currentPageId, shareLinkId, revisionId, initialData);
 
   return swrResult;
 };
@@ -141,11 +142,6 @@ export const useSWRxApplicableGrant = (
   );
 };
 
-export const useRequestRevisionPage = (initialData?: IPagePopulatedToShowRevision): SWRResponse<IPagePopulatedToShowRevision, Error> => {
-  return useStaticSWR('requestRevisionPage', initialData);
-};
-
-
 /** **********************************************************
  *                     Computed states
  *********************************************************** */