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

+ 4 - 3
packages/app/src/components/PageAccessoriesModal.tsx

@@ -5,8 +5,9 @@ import {
   Modal, ModalBody, ModalHeader,
 } from 'reactstrap';
 
-
-import { useDisableLinkSharing, useIsGuestUser, useIsSharedUser } from '~/stores/context';
+import {
+  useDisableLinkSharing, useIsGuestUser, useIsSharedUser,
+} from '~/stores/context';
 import { usePageAccessoriesModal, PageAccessoriesModalContents } from '~/stores/modal';
 
 import { CustomNavTab } from './CustomNavigation/CustomNav';
@@ -16,7 +17,7 @@ import AttachmentIcon from './Icons/AttachmentIcon';
 import HistoryIcon from './Icons/HistoryIcon';
 import ShareLinkIcon from './Icons/ShareLinkIcon';
 import PageAttachment from './PageAttachment';
-import PageHistory from './PageHistory';
+import { PageHistory } from './PageHistory';
 import ShareLink from './ShareLink/ShareLink';
 
 import styles from './PageAccessoriesModal.module.scss';

+ 17 - 13
packages/app/src/components/PageHistory.jsx → packages/app/src/components/PageHistory.tsx

@@ -1,21 +1,27 @@
 import React, { useState, useEffect } from 'react';
 
+import { IRevision, IRevisionHasPageId } from '@growi/core';
+
 import { useCurrentPageId } from '~/stores/context';
 import { useSWRxPageRevisions } from '~/stores/page';
 import loggerFactory from '~/utils/logger';
 
 import PageRevisionTable from './PageHistory/PageRevisionTable';
 import PaginationWrapper from './PaginationWrapper';
-import RevisionComparer from './RevisionComparer/RevisionComparer';
+import { RevisionComparer } from './RevisionComparer/RevisionComparer';
 
 const logger = loggerFactory('growi:PageHistory');
 
-const PageHistory = () => {
+export const PageHistory = (): JSX.Element => {
+
   const [activePage, setActivePage] = useState(1);
+
   const { data: currentPageId } = useCurrentPageId();
-  const { data: revisionsData } = useSWRxPageRevisions(currentPageId, activePage, 10);
-  const [sourceRevision, setSourceRevision] = useState(null);
-  const [targetRevision, setTargetRevision] = useState(null);
+
+  const { data: revisionsData } = useSWRxPageRevisions(activePage, 10, currentPageId);
+
+  const [sourceRevision, setSourceRevision] = useState<IRevision>();
+  const [targetRevision, setTargetRevision] = useState<IRevision>();
 
   useEffect(() => {
     if (revisionsData != null) {
@@ -24,17 +30,17 @@ const PageHistory = () => {
     }
   }, [revisionsData]);
 
-
   const pagingLimit = 10;
 
-  if (revisionsData == null) {
+  if (revisionsData == null || sourceRevision == null || targetRevision == null || currentPageId == null) {
     return (
       <div className="text-muted text-center">
         <i className="fa fa-2x fa-spinner fa-pulse mt-3"></i>
       </div>
     );
   }
-  function pager() {
+
+  const pager = () => {
     return (
       <PaginationWrapper
         activePage={activePage}
@@ -44,7 +50,7 @@ const PageHistory = () => {
         align="center"
       />
     );
-  }
+  };
 
   return (
     <div className="revision-history" data-testid="page-history">
@@ -60,12 +66,10 @@ const PageHistory = () => {
         {pager()}
       </div>
       <RevisionComparer
-        sourceRevision={sourceRevision}
-        targetRevision={targetRevision}
+        sourceRevision={sourceRevision as IRevisionHasPageId}
+        targetRevision={targetRevision as IRevisionHasPageId}
         currentPageId={currentPageId}
       />
     </div>
   );
 };
-
-export default PageHistory;

+ 0 - 87
packages/app/src/components/PageHistory/RevisionDiff.jsx

@@ -1,87 +0,0 @@
-/* eslint-disable react/no-danger */
-import React from 'react';
-
-
-import { createPatch } from 'diff';
-import { html } from 'diff2html';
-import { useTranslation } from 'next-i18next';
-import PropTypes from 'prop-types';
-
-import UserDate from '../User/UserDate';
-
-class RevisionDiff extends React.Component {
-
-  render() {
-    const { t } = this.props;
-    const currentRevision = this.props.currentRevision;
-    const previousRevision = this.props.previousRevision;
-    const revisionDiffOpened = this.props.revisionDiffOpened;
-
-
-    let diffViewHTML = '';
-    if (currentRevision.body
-      && previousRevision.body
-      && revisionDiffOpened) {
-
-      let previousText = previousRevision.body;
-      // comparing ObjectId
-      // eslint-disable-next-line eqeqeq
-      if (currentRevision._id == previousRevision._id) {
-        previousText = '';
-      }
-
-      const patch = createPatch(
-        currentRevision.pageId, // currentRevision.path is DEPRECATED
-        previousText,
-        currentRevision.body,
-      );
-      const option = {
-        drawFileList: false,
-        outputFormat: 'side-by-side',
-      };
-
-      diffViewHTML = html(patch, option);
-    }
-
-    const diffView = { __html: diffViewHTML };
-    return (
-      <>
-        <div className="comparison-header">
-          <div className="container pt-1 pr-0">
-            <div className="row">
-              <div className="col comparison-source-wrapper pt-1 px-0">
-                <span className="comparison-source pr-3">{t('page_history.comparing_source')}</span><UserDate dateTime={previousRevision.createdAt} />
-                <a href={`?revisionId=${previousRevision._id}`} className="ml-3">
-                  <i className="icon-login"></i>
-                </a>
-
-              </div>
-              <div className="col comparison-target-wrapper pt-1">
-                <span className="comparison-target pr-3">{t('page_history.comparing_target')}</span><UserDate dateTime={currentRevision.createdAt} />
-                <a href={`?revisionId=${currentRevision._id}`} className="ml-3">
-                  <i className="icon-login"></i>
-                </a>
-              </div>
-            </div>
-          </div>
-        </div>
-        <div className="revision-history-diff pb-1" dangerouslySetInnerHTML={diffView} />
-      </>
-    );
-  }
-
-}
-
-RevisionDiff.propTypes = {
-  t: PropTypes.func.isRequired,
-  currentRevision: PropTypes.object.isRequired,
-  previousRevision: PropTypes.object.isRequired,
-  revisionDiffOpened: PropTypes.bool.isRequired,
-};
-
-const RevisionDiffWrapperFC = (props) => {
-  const { t } = useTranslation();
-  return <RevisionDiff t={t} {...props} />;
-};
-
-export default RevisionDiffWrapperFC;

+ 73 - 0
packages/app/src/components/PageHistory/RevisionDiff.tsx

@@ -0,0 +1,73 @@
+import React from 'react';
+
+import { IRevisionHasPageId } from '@growi/core';
+import { createPatch } from 'diff';
+import { html, Diff2HtmlConfig } from 'diff2html';
+import { useTranslation } from 'next-i18next';
+
+import UserDate from '../User/UserDate';
+
+type RevisioinDiffProps = {
+  currentRevision: IRevisionHasPageId,
+  previousRevision: IRevisionHasPageId,
+  revisionDiffOpened: boolean,
+}
+
+export const RevisionDiff = (props: RevisioinDiffProps): JSX.Element => {
+  const { t } = useTranslation();
+
+  const { currentRevision, previousRevision, revisionDiffOpened } = props;
+
+  let diffViewHTML = '';
+  if (currentRevision.body
+    && previousRevision.body
+    && revisionDiffOpened) {
+
+    let previousText = previousRevision.body;
+    // comparing ObjectId
+    // eslint-disable-next-line eqeqeq
+    if (currentRevision._id == previousRevision._id) {
+      previousText = '';
+    }
+
+    const patch = createPatch(
+      currentRevision.pageId, // currentRevision.path is DEPRECATED
+      previousText,
+      currentRevision.body,
+    );
+    const option: Diff2HtmlConfig = {
+      outputFormat: 'side-by-side',
+      drawFileList: false,
+    };
+
+    diffViewHTML = html(patch, option);
+  }
+
+  const diffView = { __html: diffViewHTML };
+
+  return (
+    <>
+      <div className="comparison-header">
+        <div className="container pt-1 pr-0">
+          <div className="row">
+            <div className="col comparison-source-wrapper pt-1 px-0">
+              <span className="comparison-source pr-3">{t('page_history.comparing_source')}</span><UserDate dateTime={previousRevision.createdAt} />
+              <a href={`?revisionId=${previousRevision._id}`} className="ml-3">
+                <i className="icon-login"></i>
+              </a>
+
+            </div>
+            <div className="col comparison-target-wrapper pt-1">
+              <span className="comparison-target pr-3">{t('page_history.comparing_target')}</span><UserDate dateTime={currentRevision.createdAt} />
+              <a href={`?revisionId=${currentRevision._id}`} className="ml-3">
+                <i className="icon-login"></i>
+              </a>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div className="revision-history-diff pb-1" dangerouslySetInnerHTML={diffView} />
+    </>
+  );
+
+};

+ 16 - 24
packages/app/src/components/RevisionComparer/RevisionComparer.jsx → packages/app/src/components/RevisionComparer/RevisionComparer.tsx

@@ -1,8 +1,7 @@
-import React, { useState, useEffect } from 'react';
+import React, { useState } from 'react';
 
-import { pagePathUtils } from '@growi/core';
+import { IRevisionHasPageId, pagePathUtils } from '@growi/core';
 import { useTranslation } from 'next-i18next';
-import PropTypes from 'prop-types';
 import { CopyToClipboard } from 'react-copy-to-clipboard';
 import {
   Dropdown, DropdownToggle, DropdownMenu, DropdownItem,
@@ -10,31 +9,33 @@ import {
 
 import { useCurrentPagePath } from '~/stores/context';
 
-import RevisionDiff from '../PageHistory/RevisionDiff';
-
+import { RevisionDiff } from '../PageHistory/RevisionDiff';
 
 const { encodeSpaces } = pagePathUtils;
 
-/* eslint-disable react/prop-types */
 const DropdownItemContents = ({ title, contents }) => (
   <>
     <div className="h6 mt-1 mb-2"><strong>{title}</strong></div>
     <div className="card well mb-1 p-2">{contents}</div>
   </>
 );
-/* eslint-enable react/prop-types */
-
 
-const RevisionComparer = (props) => {
+type RevisionComparerProps = {
+  sourceRevision: IRevisionHasPageId
+  targetRevision: IRevisionHasPageId
+  currentPageId?: string
+}
 
+export const RevisionComparer = (props: RevisionComparerProps): JSX.Element => {
   const { t } = useTranslation();
-  const { data: currentPagePath } = useCurrentPagePath();
-  const [dropdownOpen, setDropdownOpen] = useState(false);
+
   const {
-    sourceRevision, targetRevision,
-    currentPageId,
+    sourceRevision, targetRevision, currentPageId,
   } = props;
 
+  const { data: currentPagePath } = useCurrentPagePath();
+  const [dropdownOpen, setDropdownOpen] = useState(false);
+
   function toggleDropdown() {
     setDropdownOpen(!dropdownOpen);
   }
@@ -49,11 +50,10 @@ const RevisionComparer = (props) => {
       url.searchParams.set('compare', urlParams);
     }
 
-    return encodeSpaces(decodeURI(url));
-
+    return encodeSpaces(decodeURI(url.href));
   };
 
-  let isNodiff;
+  let isNodiff: boolean;
   if (sourceRevision == null || targetRevision == null) {
     isNodiff = true;
   }
@@ -115,11 +115,3 @@ const RevisionComparer = (props) => {
     </div>
   );
 };
-
-RevisionComparer.propTypes = {
-  sourceRevision: PropTypes.instanceOf(Object),
-  targetRevision: PropTypes.instanceOf(Object),
-  currentPageId: PropTypes.string,
-};
-
-export default RevisionComparer;

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

@@ -99,9 +99,9 @@ export const useSWRxPageInfo = (
 };
 
 export const useSWRxPageRevisions = (
-    pageId: string,
     page: number, // page number of pagination
     limit: number, // max number of pages in one paginate
+    pageId: string | null | undefined,
 ): SWRResponse<IRevisionsForPagination, Error> => {
 
   return useSWRImmutable<IRevisionsForPagination, Error>(

+ 3 - 0
packages/core/src/interfaces/has-page-id.ts

@@ -0,0 +1,3 @@
+export type HasPageId = {
+  pageId: string,
+};

+ 3 - 0
packages/core/src/interfaces/revision.ts

@@ -1,4 +1,5 @@
 import { HasObjectId } from './has-object-id';
+import { HasPageId } from './has-page-id';
 import { IUser } from './user';
 
 export type IRevision = {
@@ -11,6 +12,8 @@ export type IRevision = {
 
 export type IRevisionHasId = IRevision & HasObjectId;
 
+export type IRevisionHasPageId = IRevisionHasId & HasPageId;
+
 export type IRevisionsForPagination = {
   revisions: IRevision[], // revisions in one pagination
   totalCounts: number // total counts