Jelajahi Sumber

implement useAutoComparingRevisionsByQueryParam

Yuki Takei 2 tahun lalu
induk
melakukan
39972acfe0

+ 1 - 1
apps/app/src/components/Admin/Security/ShareLinkSetting.tsx

@@ -8,8 +8,8 @@ import AdminGeneralSecurityContainer from '~/client/services/AdminGeneralSecurit
 import { apiv3Delete } from '~/client/util/apiv3-client';
 import { toastSuccess, toastError } from '~/client/util/toastr';
 
+import ShareLinkList from '../../PageAccessoriesModal/ShareLink/ShareLinkList';
 import PaginationWrapper from '../../PaginationWrapper';
-import ShareLinkList from '../../ShareLink/ShareLinkList';
 import { withUnstatedContainers } from '../../UnstatedUtils';
 
 import DeleteAllShareLinksModal from './DeleteAllShareLinksModal';

+ 12 - 32
apps/app/src/components/PageAccessoriesModal/PageAccessoriesModal.tsx

@@ -1,6 +1,7 @@
-import React, { useEffect, useMemo, useState } from 'react';
+import React, { useMemo, useState } from 'react';
 
 import { useTranslation } from 'next-i18next';
+import dynamic from 'next/dynamic';
 import {
   Modal, ModalBody, ModalHeader,
 } from 'reactstrap';
@@ -16,21 +17,21 @@ import ExpandOrContractButton from '../ExpandOrContractButton';
 import AttachmentIcon from '../Icons/AttachmentIcon';
 import HistoryIcon from '../Icons/HistoryIcon';
 import ShareLinkIcon from '../Icons/ShareLinkIcon';
-import PageAttachment from '../PageAttachment';
-import { PageHistory, getQueryParam } from '../PageHistory';
-import ShareLink from '../ShareLink/ShareLink';
 
-import { useOpenModalByQueryParam } from './open-modal-by-query-param';
+import { useAutoOpenModalByQueryParam } from './hooks';
 
 import styles from './PageAccessoriesModal.module.scss';
 
+
+const PageAttachment = dynamic(() => import('./PageAttachment'), { ssr: false });
+const PageHistory = dynamic(() => import('./PageHistory').then(mod => mod.PageHistory), { ssr: false });
+const ShareLink = dynamic(() => import('./ShareLink').then(mod => mod.ShareLink), { ssr: false });
+
+
 export const PageAccessoriesModal = (): JSX.Element => {
 
   const { t } = useTranslation();
 
-  const [sourceRevisionId, setSourceRevisionId] = useState<string>();
-  const [targetRevisionId, setTargetRevisionId] = useState<string>();
-
   const [isWindowExpanded, setIsWindowExpanded] = useState(false);
 
   const { data: isSharedUser } = useIsSharedUser();
@@ -40,35 +41,14 @@ export const PageAccessoriesModal = (): JSX.Element => {
 
   const { data: status, close, selectContents } = usePageAccessoriesModal();
 
-  useOpenModalByQueryParam();
-
-  // Set sourceRevisionId and targetRevisionId as state with valid object id string
-  useEffect(() => {
-    const queryParams = getQueryParam();
-    // https://regex101.com/r/YHTDsr/1
-    const regex = /^([0-9a-f]{24})...([0-9a-f]{24})$/i;
-
-    if (queryParams == null || !regex.test(queryParams)) {
-      return;
-    }
-
-    const matches = queryParams.match(regex);
-
-    if (matches == null) {
-      return;
-    }
-
-    const [, sourceRevisionId, targetRevisionId] = matches;
-    setSourceRevisionId(sourceRevisionId);
-    setTargetRevisionId(targetRevisionId);
-  }, []);
+  useAutoOpenModalByQueryParam();
 
   const navTabMapping = useMemo(() => {
     return {
       [PageAccessoriesModalContents.PageHistory]: {
         Icon: HistoryIcon,
         Content: () => {
-          return <PageHistory onClose={close} sourceRevisionId={sourceRevisionId} targetRevisionId={targetRevisionId}/>;
+          return <PageHistory onClose={close} />;
         },
         i18n: t('History'),
         isLinkEnabled: () => !isGuestUser && !isSharedUser,
@@ -89,7 +69,7 @@ export const PageAccessoriesModal = (): JSX.Element => {
         isLinkEnabled: () => !isGuestUser && !isReadOnlyUser && !isSharedUser && !isLinkSharingDisabled,
       },
     };
-  }, [t, close, sourceRevisionId, targetRevisionId, isGuestUser, isReadOnlyUser, isSharedUser, isLinkSharingDisabled]);
+  }, [t, close, isGuestUser, isReadOnlyUser, isSharedUser, isLinkSharingDisabled]);
 
   const buttons = useMemo(() => (
     <div className="d-flex flex-nowrap">

+ 2 - 2
apps/app/src/components/PageAttachment.tsx → apps/app/src/components/PageAccessoriesModal/PageAttachment.tsx

@@ -9,8 +9,8 @@ import { useIsGuestUser, useIsReadOnlyUser } from '~/stores/context';
 import { useDeleteAttachmentModal } from '~/stores/modal';
 import { useSWRxCurrentPage, useCurrentPageId } from '~/stores/page';
 
-import { PageAttachmentList } from './PageAttachment/PageAttachmentList';
-import PaginationWrapper from './PaginationWrapper';
+import { PageAttachmentList } from '../PageAttachment/PageAttachmentList';
+import PaginationWrapper from '../PaginationWrapper';
 
 // Utility
 const checkIfFileInUse = (markdown: string, attachment): boolean => {

+ 8 - 12
apps/app/src/components/PageHistory.tsx → apps/app/src/components/PageAccessoriesModal/PageHistory.tsx

@@ -3,34 +3,30 @@ import React from 'react';
 import { useCurrentPagePath, useCurrentPageId } from '~/stores/page';
 import loggerFactory from '~/utils/logger';
 
-import { PageRevisionTable } from './PageHistory/PageRevisionTable';
+import { PageRevisionTable } from '../PageHistory/PageRevisionTable';
+
+import { useAutoComparingRevisionsByQueryParam } from './hooks';
 
 const logger = loggerFactory('growi:PageHistory');
 
 type PageHistoryProps = {
-  sourceRevisionId?: string,
-  targetRevisionId?: string
   onClose: () => void
 }
 
-// Get string from 'compare' query params
-export const getQueryParam = (): string | null => {
-  const query: URLSearchParams = new URL(window.location.href).searchParams;
-  return query.get('compare');
-};
-
 export const PageHistory: React.FC<PageHistoryProps> = (props: PageHistoryProps) => {
-  const { sourceRevisionId, targetRevisionId, onClose } = props;
+  const { onClose } = props;
 
   const { data: currentPageId } = useCurrentPageId();
   const { data: currentPagePath } = useCurrentPagePath();
 
+  const comparingRevisions = useAutoComparingRevisionsByQueryParam();
+
   return (
     <div className="revision-history" data-testid="page-history">
       {currentPageId != null && currentPagePath != null && (
         <PageRevisionTable
-          sourceRevisionId={sourceRevisionId}
-          targetRevisionId={targetRevisionId}
+          sourceRevisionId={comparingRevisions?.sourceRevisionId}
+          targetRevisionId={comparingRevisions?.targetRevisionId}
           currentPageId={currentPageId}
           currentPagePath={currentPagePath}
           onClose={onClose}

+ 1 - 3
apps/app/src/components/ShareLink/ShareLink.tsx → apps/app/src/components/PageAccessoriesModal/ShareLink/ShareLink.tsx

@@ -12,7 +12,7 @@ import { useSWRxSharelink } from '~/stores/share-link';
 import { ShareLinkForm } from './ShareLinkForm';
 import ShareLinkList from './ShareLinkList';
 
-const ShareLink = (): JSX.Element => {
+export const ShareLink = (): JSX.Element => {
   const { t } = useTranslation();
   const [isOpenShareLinkForm, setIsOpenShareLinkForm] = useState<boolean>(false);
 
@@ -73,5 +73,3 @@ const ShareLink = (): JSX.Element => {
     </div>
   );
 };
-
-export default ShareLink;

+ 0 - 0
apps/app/src/components/ShareLink/ShareLinkForm.tsx → apps/app/src/components/PageAccessoriesModal/ShareLink/ShareLinkForm.tsx


+ 1 - 1
apps/app/src/components/ShareLink/ShareLinkList.tsx → apps/app/src/components/PageAccessoriesModal/ShareLink/ShareLinkList.tsx

@@ -3,7 +3,7 @@ import React from 'react';
 import dateFnsFormat from 'date-fns/format';
 import { useTranslation } from 'next-i18next';
 
-import CopyDropdown from '../Page/CopyDropdown';
+import CopyDropdown from '../../Page/CopyDropdown';
 
 
 type ShareLinkTrProps = {

+ 1 - 0
apps/app/src/components/PageAccessoriesModal/ShareLink/index.ts

@@ -0,0 +1 @@
+export * from './ShareLink';

+ 79 - 0
apps/app/src/components/PageAccessoriesModal/hooks.tsx

@@ -0,0 +1,79 @@
+import { useEffect, useState } from 'react';
+
+import { usePageAccessoriesModal, PageAccessoriesModalContents } from '~/stores/modal';
+
+function getURLQueryParamValue(key: string) {
+// window.location.href is page URL;
+  const queryStr: URLSearchParams = new URL(window.location.href).searchParams;
+  return queryStr.get(key);
+}
+
+// https://regex101.com/r/YHTDsr/1
+const queryCompareFormat = /^([0-9a-f]{24})...([0-9a-f]{24})$/i;
+
+
+export const useAutoOpenModalByQueryParam = (): void => {
+  const [isArleadyMounted, setIsArleadyMounted] = useState(false);
+
+  const { data: status, open: openPageAccessories } = usePageAccessoriesModal();
+
+  useEffect(() => {
+    if (isArleadyMounted) {
+      return;
+    }
+
+    if (status == null || status.isOpened === true) {
+      return;
+    }
+
+    const pageIdParams = getURLQueryParamValue('compare');
+    if (pageIdParams != null) {
+      const matches = pageIdParams.match(queryCompareFormat);
+
+      if (matches == null) {
+        return;
+      }
+
+      // open History
+      openPageAccessories(PageAccessoriesModalContents.PageHistory);
+    }
+
+    setIsArleadyMounted(true);
+  }, [openPageAccessories, status, isArleadyMounted]);
+
+};
+
+type ComparingRevisionIds = {
+  sourceRevisionId: string,
+  targetRevisionId: string,
+}
+
+export const useAutoComparingRevisionsByQueryParam = (): ComparingRevisionIds | null => {
+  const [isArleadyMounted, setIsArleadyMounted] = useState(false);
+
+  const [sourceRevisionId, setSourceRevisionId] = useState<string>();
+  const [targetRevisionId, setTargetRevisionId] = useState<string>();
+
+  useEffect(() => {
+    if (isArleadyMounted) {
+      return;
+    }
+
+    const pageIdParams = getURLQueryParamValue('compare');
+    if (pageIdParams != null) {
+      const matches = pageIdParams.match(queryCompareFormat);
+
+      if (matches != null) {
+        const [, source, target] = matches;
+        setSourceRevisionId(source);
+        setTargetRevisionId(target);
+      }
+    }
+
+    setIsArleadyMounted(true);
+  }, [isArleadyMounted]);
+
+  return sourceRevisionId != null && targetRevisionId != null
+    ? { sourceRevisionId, targetRevisionId }
+    : null;
+};

+ 0 - 33
apps/app/src/components/PageAccessoriesModal/open-modal-by-query-param.tsx

@@ -1,33 +0,0 @@
-import { useEffect, useState } from 'react';
-
-import { usePageAccessoriesModal, PageAccessoriesModalContents } from '~/stores/modal';
-
-function getURLQueryParamValue(key: string) {
-// window.location.href is page URL;
-  const queryStr: URLSearchParams = new URL(window.location.href).searchParams;
-  return queryStr.get(key);
-}
-
-const queryCompareFormat = new RegExp(/([a-z0-9]){24}...([a-z0-9]){24}/);
-
-export const useOpenModalByQueryParam = (): void => {
-  const { data: status, open: openPageAccessories } = usePageAccessoriesModal();
-  const [isArleadyMounted, setIsArleadyMounted] = useState(false);
-
-  useEffect(() => {
-    const pageIdParams = getURLQueryParamValue('compare');
-    if (status == null || status.isOpened === true) {
-      return;
-    }
-    if (isArleadyMounted === true) {
-      return;
-    }
-    if (pageIdParams != null) {
-      if (queryCompareFormat.test(pageIdParams)) {
-        openPageAccessories(PageAccessoriesModalContents.PageHistory);
-      }
-    }
-    setIsArleadyMounted(true);
-  }, [openPageAccessories, status, isArleadyMounted]);
-
-};