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

Merge pull request #6260 from weseek/support/delete-appcontainer-for-PageComments

support: delete appcontainer for page comments
ryoji-s 3 лет назад
Родитель
Сommit
af3be18c2a

+ 5 - 8
packages/app/src/components/PageComment.tsx

@@ -2,10 +2,10 @@ import React, {
   FC, useEffect, useState, useMemo, memo, useCallback,
 } from 'react';
 
+import { Nullable } from '^/../core/src/interfaces/common';
 import { Button } from 'reactstrap';
 
 
-import AppContainer from '~/client/services/AppContainer';
 import { toastError } from '~/client/util/apiNotification';
 import { apiPost } from '~/client/util/apiv1-client';
 import { useCommentPreviewOptions } from '~/stores/renderer';
@@ -20,19 +20,18 @@ import DeleteCommentModal from './PageComment/DeleteCommentModal';
 import ReplayComments from './PageComment/ReplayComments';
 
 type Props = {
-  appContainer: AppContainer,
-  pageId: string,
+  // TODO: Do not use Nullable, create presentaion for if cannot get pageId.
+  pageId?: Nullable<string>,
   isReadOnly : boolean,
   titleAlign?: 'center' | 'left' | 'right',
   highlightKeywords?:string[],
   hideIfEmpty?: boolean,
 }
 
-
-const PageComment:FC<Props> = memo((props:Props):JSX.Element => {
+export const PageComment:FC<Props> = memo((props:Props):JSX.Element => {
 
   const {
-    appContainer, pageId, highlightKeywords, isReadOnly, titleAlign, hideIfEmpty,
+    pageId, highlightKeywords, isReadOnly, titleAlign, hideIfEmpty,
   } = props;
 
   const { data: comments, mutate } = useSWRxPageComment(pageId);
@@ -224,5 +223,3 @@ const PageComment:FC<Props> = memo((props:Props):JSX.Element => {
 });
 
 PageComment.displayName = 'PageComment';
-
-export default PageComment;

+ 52 - 30
packages/app/src/components/PageComment/Comment.jsx

@@ -6,20 +6,23 @@ import PropTypes from 'prop-types';
 import { useTranslation } from 'next-i18next';
 import { UncontrolledTooltip } from 'reactstrap';
 
-import AppContainer from '~/client/services/AppContainer';
-import PageContainer from '~/client/services/PageContainer';
-import { useCurrentUser } from '~/stores/context';
+import {
+  useCurrentUser, useRevisionId, useRevisionCreatedAt, useRendererConfig, useInterceptorManager,
+} from '~/stores/context';
 
 import FormattedDistanceDate from '../FormattedDistanceDate';
 import HistoryIcon from '../Icons/HistoryIcon';
 import RevisionBody from '../Page/RevisionBody';
-import { withUnstatedContainers } from '../UnstatedUtils';
 import Username from '../User/Username';
 
 import CommentControl from './CommentControl';
 import CommentEditor from './CommentEditor';
 
 import { RendererOptions } from '~/services/renderer/renderer';
+import { RendererConfig } from '~/interfaces/services/renderer';
+import InterceptorManager from '~/services/interceptor-manager';
+import loggerFactory from '~/utils/logger';
+const logger = loggerFactory('growi:Page');
 
 /**
  *
@@ -70,7 +73,7 @@ class Comment extends React.PureComponent {
       return;
     }
 
-    const { interceptorManager } = window;
+    const { interceptorManager } = this.props;
 
     interceptorManager.process('postRenderCommentHtml', this.currentRenderingContext);
   }
@@ -86,13 +89,14 @@ class Comment extends React.PureComponent {
   }
 
   isCurrentRevision() {
-    return this.props.comment.revision === this.props.pageContainer.state.revisionId;
+    const { revisionId } = this.props;
+    return this.props.comment.revision === revisionId;
   }
 
   getRootClassName(comment) {
     let className = 'page-comment flex-column';
 
-    const { revisionId, revisionCreatedAt } = this.props.pageContainer.state;
+    const { revisionId, revisionCreatedAt } = this.props;
     if (comment.revision === revisionId) {
       className += ' page-comment-current';
     }
@@ -119,12 +123,13 @@ class Comment extends React.PureComponent {
   }
 
   renderRevisionBody() {
-    const config = this.props.appContainer.getConfig();
-    const isMathJaxEnabled = !!config.env.MATHJAX;
+    const { config } = this.props;
+    // TODO: Check isMathJaxEnabled when remarked.
+    // const isMathJaxEnabled = !!config.env.MATHJAX;
     return (
       <RevisionBody
         html={this.state.html}
-        isMathJaxEnabled={isMathJaxEnabled}
+        // isMathJaxEnabled={isMathJaxEnabled}
         renderMathJaxOnInit
         additionalClassName="comment"
       />
@@ -132,18 +137,17 @@ class Comment extends React.PureComponent {
   }
 
   async renderHtml() {
-
-    const { rendererOptions, appContainer } = this.props;
-    const { interceptorManager } = window;
+    // TODO: Check rendererOptions when remarked.
+    const { interceptorManager, rendererOptions } = this.props;
     const context = this.currentRenderingContext;
 
     await interceptorManager.process('preRenderComment', context);
     await interceptorManager.process('prePreProcess', context);
-    context.markdown = await rendererOptions.preProcess(context.markdown, context);
+    // context.markdown = await rendererOptions.preProcess(context.markdown, context);
     await interceptorManager.process('postPreProcess', context);
-    context.parsedHTML = await rendererOptions.process(context.markdown, context);
+    // context.parsedHTML = await rendererOptions.process(context.markdown, context);
     await interceptorManager.process('prePostProcess', context);
-    context.parsedHTML = await rendererOptions.postProcess(context.parsedHTML, context);
+    // context.parsedHTML = await rendererOptions.postProcess(context.parsedHTML, context);
     await interceptorManager.process('postPostProcess', context);
     await interceptorManager.process('preRenderCommentHtml', context);
     this.setState({ html: context.parsedHTML });
@@ -152,7 +156,7 @@ class Comment extends React.PureComponent {
 
   render() {
     const {
-      t, comment, isReadOnly, onComment,
+      t, comment, isReadOnly, onComment, rendererOptions
     } = this.props;
     const commentId = comment._id;
     const creator = comment.creator;
@@ -174,7 +178,7 @@ class Comment extends React.PureComponent {
       <React.Fragment>
         {(this.state.isReEdit && !isReadOnly) ? (
           <CommentEditor
-            rendererOptions={this.props.rendererOptions}
+            rendererOptions={rendererOptions}
             currentCommentId={commentId}
             commentBody={comment.comment}
             replyTo={undefined}
@@ -232,28 +236,46 @@ class Comment extends React.PureComponent {
 
 Comment.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-  pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
 
   comment: PropTypes.object.isRequired,
   isReadOnly: PropTypes.bool.isRequired,
-  rendererOptions: PropTypes.instanceOf(RendererOptions).isRequired,
+  // rendererOptions: PropTypes.instanceOf(RendererOptions).isRequired,
   deleteBtnClicked: PropTypes.func.isRequired,
-  currentUser: PropTypes.object,
+  currentUser: PropTypes.object.isRequired,
   onComment: PropTypes.func,
+  // revisionId: PropTypes.string.isRequired,
+  // revisionCreatedAt: PropTypes.instanceOf(Date).isRequired,
+  // config: PropTypes.instanceOf(RendererConfig),
+  // interceptorManager: PropTypes.instanceOf(InterceptorManager),
 };
 
 const CommentWrapperFC = (props) => {
   const { t } = useTranslation();
 
   const { data: currentUser } = useCurrentUser();
-
-  return <Comment t={t} currentUser={currentUser} {...props} />;
+  const { data: revisionId } = useRevisionId();
+  const { data: revisionCreatedAt } = useRevisionCreatedAt();
+  const { data: config } = useRendererConfig();
+  const { data: interceptorManager } = useInterceptorManager();
+
+  // // TODO: Check if imported null values
+  // if (revisionId == null || revisionCreatedAt == null) {
+  //   logger.warn('Some comment materials are missing.', {
+  //     currentUser, revisionId, revisionCreatedAt, config, interceptorManager,
+  //   });
+  //   return null;
+  // }
+
+  return (
+    <Comment
+      t={t}
+      currentUser={currentUser}
+      revisionId={revisionId}
+      revisionCreatedAt={revisionCreatedAt}
+      config={config}
+      interceptorManager={interceptorManager}
+      {...props}
+    />);
 };
 
-/**
- * Wrapper component for using unstated
- */
-const CommentWrapper = withUnstatedContainers(CommentWrapperFC, [AppContainer, PageContainer]);
-
-export default CommentWrapper;
+export default CommentWrapperFC;

+ 4 - 17
packages/app/src/components/PageComment/CommentEditor.tsx

@@ -9,16 +9,13 @@ import {
 } from 'reactstrap';
 import * as toastr from 'toastr';
 
-import AppContainer from '~/client/services/AppContainer';
-import EditorContainer from '~/client/services/EditorContainer';
-import PageContainer from '~/client/services/PageContainer';
 import { apiPostForm } from '~/client/util/apiv1-client';
 import { CustomWindow } from '~/interfaces/global';
 import { IInterceptorManager } from '~/interfaces/interceptor-manager';
 import { RendererOptions } from '~/services/renderer/renderer';
 import { useSWRxPageComment } from '~/stores/comment';
 import {
-  useCurrentPagePath, useCurrentPageId, useCurrentUser, useRevisionId,
+  useCurrentPagePath, useCurrentPageId, useCurrentUser, useRevisionId, useRendererConfig,
 } from '~/stores/context';
 import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
 import { useIsMobile } from '~/stores/ui';
@@ -28,7 +25,6 @@ import { CustomNavTab } from '../CustomNavigation/CustomNav';
 import NotAvailableForGuest from '../NotAvailableForGuest';
 import Editor from '../PageEditor/Editor';
 import { SlackNotification } from '../SlackNotification';
-import { withUnstatedContainers } from '../UnstatedUtils';
 
 import CommentPreview from './CommentPreview';
 
@@ -47,8 +43,6 @@ const navTabMapping = {
 };
 
 type PropsType = {
-  appContainer: AppContainer,
-
   rendererOptions: RendererOptions,
   isForNewComment?: boolean,
   replyTo?: string,
@@ -68,7 +62,7 @@ type EditorRef = {
 const CommentEditor = (props: PropsType): JSX.Element => {
 
   const {
-    appContainer, rendererOptions, isForNewComment, replyTo,
+    rendererOptions, isForNewComment, replyTo,
     currentCommentId, commentBody, commentCreator, onCancelButtonClicked, onCommentButtonClicked,
   } = props;
   const { data: currentUser } = useCurrentUser();
@@ -79,8 +73,8 @@ const CommentEditor = (props: PropsType): JSX.Element => {
   const { data: isMobile } = useIsMobile();
   const { data: isSlackEnabled, mutate: mutateIsSlackEnabled } = useIsSlackEnabled();
   const { data: slackChannelsData } = useSWRxSlackChannels(currentPagePath);
+  const { data: config } = useRendererConfig();
 
-  const config = appContainer.getConfig();
   const isUploadable = config.upload.image || config.upload.file;
   const isUploadableFile = config.upload.file;
   const isSlackConfigured = config.isSlackConfigured;
@@ -377,11 +371,4 @@ const CommentEditor = (props: PropsType): JSX.Element => {
 
 };
 
-/**
- * Wrapper component for using unstated
- */
-const CommentEditorWrapper = withUnstatedContainers<unknown, Partial<PropsType>>(
-  CommentEditor, [AppContainer, PageContainer, EditorContainer],
-);
-
-export default CommentEditorWrapper;
+export default CommentEditor;

+ 10 - 14
packages/app/src/components/PageComment/ReplayComments.jsx

@@ -3,13 +3,10 @@ import PropTypes from 'prop-types';
 
 import { Collapse } from 'reactstrap';
 
-import AppContainer from '~/client/services/AppContainer';
-import PageContainer from '~/client/services/PageContainer';
+import { useRendererConfig } from '~/stores/context';
 
 import Comment from './Comment';
 
-import { withUnstatedContainers } from '../UnstatedUtils';
-
 import { RendererOptions } from '~/services/renderer/renderer';
 
 class ReplayComments extends React.PureComponent {
@@ -42,8 +39,9 @@ class ReplayComments extends React.PureComponent {
   }
 
   render() {
+    const { config } = this.props
 
-    const isAllReplyShown = this.props.appContainer.getConfig().isAllReplyShown || false;
+    const isAllReplyShown = config.isAllReplyShown || false;
     const replyList = this.props.replyList;
 
     if (isAllReplyShown) {
@@ -100,19 +98,17 @@ class ReplayComments extends React.PureComponent {
 
 }
 
-/**
- * Wrapper component for using unstated
- */
-const ReplayCommentsWrapper = withUnstatedContainers(ReplayComments, [AppContainer, PageContainer]);
-
 ReplayComments.propTypes = {
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-  pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
-
   rendererOptions: PropTypes.instanceOf(RendererOptions).isRequired,
   deleteBtnClicked: PropTypes.func.isRequired,
   isReadOnly: PropTypes.bool.isRequired,
   replyList: PropTypes.array,
 };
 
-export default ReplayCommentsWrapper;
+const ReplayCommentsWrapperFC = (props) => {
+  const { data: config } = useRendererConfig();
+
+  return <ReplayComments config={config} {...props} />;
+};
+
+export default ReplayCommentsWrapperFC;

+ 3 - 9
packages/app/src/components/PageEditor/DrawioModal.jsx

@@ -1,15 +1,12 @@
 import React from 'react';
-import PropTypes from 'prop-types';
-import i18next from 'i18next';
 
+import i18next from 'i18next';
+import PropTypes from 'prop-types';
 import {
   Modal,
   ModalBody,
 } from 'reactstrap';
 
-import { withUnstatedContainers } from '../UnstatedUtils';
-import AppContainer from '~/client/services/AppContainer';
-import EditorContainer from '~/client/services/EditorContainer';
 import { getDiagramsNetLangCode } from '~/client/util/locale-utils';
 
 class DrawioModal extends React.PureComponent {
@@ -168,11 +165,8 @@ class DrawioModal extends React.PureComponent {
 }
 
 DrawioModal.propTypes = {
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-  editorContainer: PropTypes.instanceOf(EditorContainer).isRequired,
-
   onSave: PropTypes.func,
 };
 
 
-export default withUnstatedContainers(DrawioModal, [AppContainer, EditorContainer]);
+export default DrawioModal;

+ 3 - 2
packages/app/src/components/PageEditor/Editor.jsx

@@ -1,5 +1,6 @@
 import React from 'react';
 
+import dynamic from 'next/dynamic';
 import PropTypes from 'prop-types';
 import Dropzone from 'react-dropzone';
 import {
@@ -11,11 +12,10 @@ import { useEditorSettings } from '~/stores/editor';
 
 import AbstractEditor from './AbstractEditor';
 import Cheatsheet from './Cheatsheet';
-import CodeMirrorEditor from './CodeMirrorEditor';
 import pasteHelper from './PasteHelper';
 import TextAreaEditor from './TextAreaEditor';
 
-
+const CodeMirrorEditor = dynamic(() => import('./CodeMirrorEditor').then(mod => mod.CodeMirrorEditor), { ssr: false });
 class Editor extends AbstractEditor {
 
   constructor(props) {
@@ -275,6 +275,7 @@ class Editor extends AbstractEditor {
 
 
   render() {
+
     const flexContainer = {
       height: '100%',
       display: 'flex',

+ 5 - 15
packages/app/src/components/PageEditor/Preview.tsx

@@ -2,14 +2,11 @@ import React, {
   useCallback, useEffect, useMemo, useState, SyntheticEvent, RefObject,
 } from 'react';
 
-
-import AppContainer from '~/client/services/AppContainer';
 import InterceptorManager from '~/services/interceptor-manager';
 import { RendererOptions } from '~/services/renderer/renderer';
 import { useEditorSettings } from '~/stores/editor';
 
 import RevisionBody from '../Page/RevisionBody';
-import { withUnstatedContainers } from '../UnstatedUtils';
 
 
 declare const interceptorManager: InterceptorManager;
@@ -23,9 +20,7 @@ type Props = {
   onScroll?: (scrollTop: number) => void,
 }
 
-type UnstatedProps = Props & { appContainer: AppContainer };
-
-const Preview = React.forwardRef((props: UnstatedProps, ref: RefObject<HTMLDivElement>): JSX.Element => {
+const Preview = React.forwardRef((props: Props, ref: RefObject<HTMLDivElement>): JSX.Element => {
 
   const {
     rendererOptions,
@@ -108,16 +103,11 @@ const Preview = React.forwardRef((props: UnstatedProps, ref: RefObject<HTMLDivEl
 
 Preview.displayName = 'Preview';
 
-/**
- * Wrapper component for using unstated
- */
-const PreviewWrapper = withUnstatedContainers(Preview, [AppContainer]);
-
 // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-const PreviewWrapper2 = React.forwardRef((props: Props, ref: RefObject<HTMLDivElement>): JSX.Element => {
-  return <PreviewWrapper ref={ref} {...props} />;
+const PreviewWrapper = React.forwardRef((props: Props, ref: RefObject<HTMLDivElement>): JSX.Element => {
+  return <Preview ref={ref} {...props} />;
 });
 
-PreviewWrapper2.displayName = 'PreviewWrapper2';
+PreviewWrapper.displayName = 'PreviewWrapper';
 
-export default PreviewWrapper2;
+export default PreviewWrapper;

+ 3 - 4
packages/app/src/pages/[[...path]].page.tsx

@@ -15,7 +15,7 @@ import Head from 'next/head';
 import { useRouter } from 'next/router';
 
 import { PageAlerts } from '~/components/PageAlert/PageAlerts';
-// import { PageComments } from '~/components/PageComment/PageComments';
+import { PageComment } from '~/components/PageComment';
 // import { useTranslation } from '~/i18n';
 import { CrowiRequest } from '~/interfaces/crowi-request';
 // import { renderScriptTagByName, renderHighlightJsStyleTag } from '~/service/cdn-resources-loader';
@@ -29,6 +29,7 @@ import { PageModel, PageDocument } from '~/server/models/page';
 import UserUISettings, { UserUISettingsDocument } from '~/server/models/user-ui-settings';
 import Xss from '~/services/xss';
 import { useSWRxCurrentPage, useSWRxPageInfo, useSWRxPage } from '~/stores/page';
+import { useCommentPreviewOptions } from '~/stores/renderer';
 import {
   usePreferDrawerModeByUser, usePreferDrawerModeOnEditByUser, useSidebarCollapsed, useCurrentSidebarContents, useCurrentProductNavWidth,
 } from '~/stores/ui';
@@ -191,7 +192,6 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
   // useRendererSettings(props.rendererSettingsStr != null ? JSON.parse(props.rendererSettingsStr) : undefined);
   // useGrowiRendererConfig(props.growiRendererConfigStr != null ? JSON.parse(props.growiRendererConfigStr) : undefined);
 
-
   // const { data: editorMode } = useEditorMode();
 
   let pageWithMeta: IPageToShowRevisionWithMeta | undefined;
@@ -286,8 +286,7 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
 
         </div>
         <footer>
-          {/* <PageComments /> */}
-          PageComments
+          <PageComment pageId={useCurrentPageId().data} isReadOnly={false} titleAlign="left" />
         </footer>
 
         <UnsavedAlertDialog />