kaori 3 лет назад
Родитель
Сommit
6cb26d59fa

+ 90 - 84
packages/app/src/components/Page.tsx

@@ -3,13 +3,15 @@ import React, {
   useEffect, useRef, useState,
 } from 'react';
 
+import EventEmitter from 'events';
+
 import dynamic from 'next/dynamic';
 // import { debounce } from 'throttle-debounce';
 
 import { HtmlElementNode } from 'rehype-toc';
 
 import { blinkSectionHeaderAtBoot } from '~/client/util/blink-section-header';
-// import { getOptionsToSave } from '~/client/util/editor';
+import { getOptionsToSave } from '~/client/util/editor';
 import {
   useIsGuestUser, useIsBlinkedHeaderAtBoot, useCurrentPageTocNode,
 } from '~/stores/context';
@@ -24,11 +26,15 @@ import {
 import loggerFactory from '~/utils/logger';
 
 import RevisionRenderer from './Page/RevisionRenderer';
+import DrawioModal from './PageEditor/DrawioModal';
+
 
 // TODO: import dynamically
 // import MarkdownTable from '~/client/models/MarkdownTable';
-// import mdu from './PageEditor/MarkdownDrawioUtil';
-// import mtu from './PageEditor/MarkdownTableUtil';
+import mdu from './PageEditor/MarkdownDrawioUtil';
+import mtu from './PageEditor/MarkdownTableUtil';
+
+declare const globalEmitter: EventEmitter;
 
 const logger = loggerFactory('growi:Page');
 
@@ -76,10 +82,10 @@ class PageSubstance extends React.Component<PageSubstanceProps> {
    * @param endLineNumber
    */
   launchHandsontableModal(beginLineNumber, endLineNumber) {
-    // const markdown = this.props.pageContainer.state.markdown;
-    // const tableLines = markdown.split(/\r\n|\r|\n/).slice(beginLineNumber - 1, endLineNumber).join('\n');
-    // this.setState({ currentTargetTableArea: { beginLineNumber, endLineNumber } });
-    // this.handsontableModal.current.show(MarkdownTable.fromMarkdownString(tableLines));
+    const markdown = this.props.pageContainer.state.markdown;
+    const tableLines = markdown.split(/\r\n|\r|\n/).slice(beginLineNumber - 1, endLineNumber).join('\n');
+    this.setState({ currentTargetTableArea: { beginLineNumber, endLineNumber } });
+    this.handsontableModal.current.show(MarkdownTable.fromMarkdownString(tableLines));
   }
 
   /**
@@ -88,75 +94,75 @@ class PageSubstance extends React.Component<PageSubstanceProps> {
    * @param endLineNumber
    */
   launchDrawioModal(beginLineNumber, endLineNumber) {
-    // const markdown = this.props.pageContainer.state.markdown;
-    // const drawioMarkdownArray = markdown.split(/\r\n|\r|\n/).slice(beginLineNumber - 1, endLineNumber);
-    // const drawioData = drawioMarkdownArray.slice(1, drawioMarkdownArray.length - 1).join('\n').trim();
-    // this.setState({ currentTargetDrawioArea: { beginLineNumber, endLineNumber } });
-    // this.drawioModal.current.show(drawioData);
+    const markdown = this.props.pageContainer.state.markdown;
+    const drawioMarkdownArray = markdown.split(/\r\n|\r|\n/).slice(beginLineNumber - 1, endLineNumber);
+    const drawioData = drawioMarkdownArray.slice(1, drawioMarkdownArray.length - 1).join('\n').trim();
+    this.setState({ currentTargetDrawioArea: { beginLineNumber, endLineNumber } });
+    this.drawioModal.current.show(drawioData);
   }
 
   async saveHandlerForHandsontableModal(markdownTable) {
-    // const {
-    //   isSlackEnabled, slackChannels, pageContainer, mutateIsEnabledUnsavedWarning, grant, grantGroupId, grantGroupName, pageTags,
-    // } = this.props;
-    // const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, pageTags);
-
-    // const newMarkdown = mtu.replaceMarkdownTableInMarkdown(
-    //   markdownTable,
-    //   this.props.pageContainer.state.markdown,
-    //   this.state.currentTargetTableArea.beginLineNumber,
-    //   this.state.currentTargetTableArea.endLineNumber,
-    // );
-
-    // try {
-    //   // disable unsaved warning
-    //   mutateIsEnabledUnsavedWarning(false);
-
-    //   // eslint-disable-next-line no-unused-vars
-    //   const { page, tags } = await pageContainer.save(newMarkdown, this.props.editorMode, optionsToSave);
-    //   logger.debug('success to save');
-
-    //   pageContainer.showSuccessToastr();
-    // }
-    // catch (error) {
-    //   logger.error('failed to save', error);
-    //   pageContainer.showErrorToastr(error);
-    // }
-    // finally {
-    //   this.setState({ currentTargetTableArea: null });
-    // }
+    const {
+      isSlackEnabled, slackChannels, pageContainer, mutateIsEnabledUnsavedWarning, grant, grantGroupId, grantGroupName, pageTags,
+    } = this.props;
+    const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, pageTags);
+
+    const newMarkdown = mtu.replaceMarkdownTableInMarkdown(
+      markdownTable,
+      this.props.pageContainer.state.markdown,
+      this.state.currentTargetTableArea.beginLineNumber,
+      this.state.currentTargetTableArea.endLineNumber,
+    );
+
+    try {
+      // disable unsaved warning
+      mutateIsEnabledUnsavedWarning(false);
+
+      // eslint-disable-next-line no-unused-vars
+      const { page, tags } = await pageContainer.save(newMarkdown, this.props.editorMode, optionsToSave);
+      logger.debug('success to save');
+
+      pageContainer.showSuccessToastr();
+    }
+    catch (error) {
+      logger.error('failed to save', error);
+      pageContainer.showErrorToastr(error);
+    }
+    finally {
+      this.setState({ currentTargetTableArea: null });
+    }
   }
 
   async saveHandlerForDrawioModal(drawioData) {
-    // const {
-    //   isSlackEnabled, slackChannels, pageContainer, pageTags, grant, grantGroupId, grantGroupName, mutateIsEnabledUnsavedWarning,
-    // } = this.props;
-    // const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, pageTags);
-
-    // const newMarkdown = mdu.replaceDrawioInMarkdown(
-    //   drawioData,
-    //   this.props.pageContainer.state.markdown,
-    //   this.state.currentTargetDrawioArea.beginLineNumber,
-    //   this.state.currentTargetDrawioArea.endLineNumber,
-    // );
-
-    // try {
-    //   // disable unsaved warning
-    //   mutateIsEnabledUnsavedWarning(false);
-
-    //   // eslint-disable-next-line no-unused-vars
-    //   const { page, tags } = await pageContainer.save(newMarkdown, this.props.editorMode, optionsToSave);
-    //   logger.debug('success to save');
-
-    //   pageContainer.showSuccessToastr();
-    // }
-    // catch (error) {
-    //   logger.error('failed to save', error);
-    //   pageContainer.showErrorToastr(error);
-    // }
-    // finally {
-    //   this.setState({ currentTargetDrawioArea: null });
-    // }
+    const {
+      isSlackEnabled, slackChannels, pageContainer, pageTags, grant, grantGroupId, grantGroupName, mutateIsEnabledUnsavedWarning,
+    } = this.props;
+    const optionsToSave = getOptionsToSave(isSlackEnabled, slackChannels, grant, grantGroupId, grantGroupName, pageTags);
+
+    const newMarkdown = mdu.replaceDrawioInMarkdown(
+      drawioData,
+      this.props.pageContainer.state.markdown,
+      this.state.currentTargetDrawioArea.beginLineNumber,
+      this.state.currentTargetDrawioArea.endLineNumber,
+    );
+
+    try {
+      // disable unsaved warning
+      mutateIsEnabledUnsavedWarning(false);
+
+      // eslint-disable-next-line no-unused-vars
+      const { page, tags } = await pageContainer.save(newMarkdown, this.props.editorMode, optionsToSave);
+      logger.debug('success to save');
+
+      pageContainer.showSuccessToastr();
+    }
+    catch (error) {
+      logger.error('failed to save', error);
+      pageContainer.showErrorToastr(error);
+    }
+    finally {
+      this.setState({ currentTargetDrawioArea: null });
+    }
   }
 
   override render() {
@@ -183,7 +189,7 @@ class PageSubstance extends React.Component<PageSubstanceProps> {
             <GridEditModal ref={this.gridEditModal} />
             <LinkEditModal ref={this.linkEditModal} />
             {/* <HandsontableModal ref={this.handsontableModal} onSave={this.saveHandlerForHandsontableModal} /> */}
-            {/* <DrawioModal ref={this.drawioModal} onSave={this.saveHandlerForDrawioModal} /> */}
+            <DrawioModal ref={this.drawioModal} onSave={this.saveHandlerForDrawioModal} />
           </>
         )}
       </div>
@@ -230,18 +236,18 @@ export const Page = (props) => {
   }, [mutateCurrentPageTocNode, tocRef.current]); // include tocRef.current to call mutateCurrentPageTocNode when tocRef.current changes
 
   // // set handler to open DrawioModal
-  // useEffect(() => {
-  //   const handler = (beginLineNumber, endLineNumber) => {
-  //     if (pageRef?.current != null) {
-  //       pageRef.current.launchDrawioModal(beginLineNumber, endLineNumber);
-  //     }
-  //   };
-  //   window.globalEmitter.on('launchDrawioModal', handler);
+  useEffect(() => {
+    const handler = (beginLineNumber, endLineNumber) => {
+      if (pageRef?.current != null) {
+        pageRef.current.launchDrawioModal(beginLineNumber, endLineNumber);
+      }
+    };
+    globalEmitter.on('launchDrawioModal', handler);
 
-  //   return function cleanup() {
-  //     window.globalEmitter.removeListener('launchDrawioModal', handler);
-  //   };
-  // }, []);
+    return function cleanup() {
+      globalEmitter.removeListener('launchDrawioModal', handler);
+    };
+  }, []);
 
   // // set handler to open HandsontableModal
   // useEffect(() => {
@@ -250,10 +256,10 @@ export const Page = (props) => {
   //       pageRef.current.launchHandsontableModal(beginLineNumber, endLineNumber);
   //     }
   //   };
-  //   window.globalEmitter.on('launchHandsontableModal', handler);
+  //   globalEmitter.on('launchHandsontableModal', handler);
 
   //   return function cleanup() {
-  //     window.globalEmitter.removeListener('launchHandsontableModal', handler);
+  //     globalEmitter.removeListener('launchHandsontableModal', handler);
   //   };
   // }, []);
 

+ 13 - 15
packages/app/src/components/PageEditor/CodeMirrorEditor.jsx

@@ -16,7 +16,7 @@ import { UncontrolledCodeMirror } from '../UncontrolledCodeMirror';
 
 import AbstractEditor from './AbstractEditor';
 import CommentMentionHelper from './CommentMentionHelper';
-// import DrawioModal from './DrawioModal';
+import DrawioModal from './DrawioModal';
 import EditorIcon from './EditorIcon';
 import EmojiPicker from './EmojiPicker';
 import EmojiPickerHelper from './EmojiPickerHelper';
@@ -229,14 +229,14 @@ class CodeMirrorEditor extends AbstractEditor {
   forceToFocus() {
     const editor = this.getCodeMirror();
     // use setInterval with reluctance -- 2018.01.11 Yuki Takei
-    const intervalId = setInterval(() => {
-      this.getCodeMirror().focus();
-      if (editor.hasFocus()) {
-        clearInterval(intervalId);
-        // refresh
-        editor.refresh();
-      }
-    }, 100);
+    // const intervalId = setInterval(() => {
+    //   this.getCodeMirror().focus();
+    //   if (editor.hasFocus()) {
+    //     clearInterval(intervalId);
+    //     // refresh
+    //     editor.refresh();
+    //   }
+    // }, 100);
   }
 
   /**
@@ -793,7 +793,7 @@ class CodeMirrorEditor extends AbstractEditor {
   }
 
   showDrawioHandler() {
-    // this.drawioModal.current.show(mdu.getMarkdownDrawioMxfile(this.getCodeMirror()));
+    this.drawioModal.current.show(mdu.getMarkdownDrawioMxfile(this.getCodeMirror()));
   }
 
 
@@ -1052,17 +1052,15 @@ class CodeMirrorEditor extends AbstractEditor {
           ref={this.linkEditModal}
           onSave={(linkText) => { return markdownLinkUtil.replaceFocusedMarkdownLinkWithEditor(this.getCodeMirror(), linkText) }}
         />
-        {/*
-        <HandsontableModal
+        {/* <HandsontableModal
           ref={this.handsontableModal}
           onSave={(table) => { return mtu.replaceFocusedMarkdownTableWithEditor(this.getCodeMirror(), table) }}
           autoFormatMarkdownTable={this.props.editorSettings.autoFormatMarkdownTable}
         /> */}
-        {/* <DrawioModal
+        <DrawioModal
           ref={this.drawioModal}
           onSave={this.onSaveForDrawio}
-        /> */}
-
+        />
       </div>
     );
   }

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

@@ -8,6 +8,8 @@ import {
 } from 'reactstrap';
 
 import { getDiagramsNetLangCode } from '~/client/util/locale-utils';
+import { useGrowiHydratedEnv } from '~/stores/context';
+
 
 class DrawioModal extends React.PureComponent {
 
@@ -115,9 +117,10 @@ class DrawioModal extends React.PureComponent {
   }
 
   get drawioURL() {
-    const { config } = this.props.appContainer;
+    // const { config } = this.props.appContainer;
+    const { drawioUriEnv } = this.props;
 
-    const drawioUri = config.env.DRAWIO_URI || 'https://embed.diagrams.net/';
+    const drawioUri = drawioUriEnv || 'https://embed.diagrams.net/';
     const url = new URL(drawioUri);
 
     // refs: https://desk.draw.io/support/solutions/articles/16000042546-what-url-parameters-are-supported-
@@ -166,7 +169,15 @@ class DrawioModal extends React.PureComponent {
 
 DrawioModal.propTypes = {
   onSave: PropTypes.func,
+  drawioUri:  PropTypes.string,
+};
+
+const DrawioModalFc = (props) => {
+  const { growiHydratedEnv } = useGrowiHydratedEnv();
+
+
+  return <DrawioModal onSave={props.onSave} drawioUri={growiHydratedEnv?.drawioUri} />;
 };
 
 
-export default DrawioModal;
+export default DrawioModalFc;

+ 7 - 7
packages/app/src/interfaces/services/renderer.ts

@@ -1,12 +1,12 @@
 import { XssOptionConfig } from '~/services/xss/xssOption';
 
-// export type GrowiHydratedEnv = {
-//   DRAWIO_URI: string | null,
-//   HACKMD_URI: string | null,
-//   NO_CDN: string | null,
-//   GROWI_CLOUD_URI: string | null,
-//   GROWI_APP_ID_FOR_GROWI_CLOUD: string | null,
-// }
+export type GrowiHydratedEnv = {
+  DRAWIO_URI: string | null,
+  HACKMD_URI: string | null,
+  NO_CDN: string | null,
+  GROWI_CLOUD_URI: string | null,
+  GROWI_APP_ID_FOR_GROWI_CLOUD: string | null,
+}
 
 export type RendererConfig = {
   isEnabledLinebreaks: boolean,

+ 12 - 7
packages/app/src/pages/[[...path]].page.tsx

@@ -28,7 +28,7 @@ import { CrowiRequest } from '~/interfaces/crowi-request';
 // import { EditorMode, useEditorMode, useIsMobile } from '~/stores/ui';
 import { EditorConfig } from '~/interfaces/editor-settings';
 import { CustomWindow } from '~/interfaces/global';
-import { RendererConfig } from '~/interfaces/services/renderer';
+import { GrowiHydratedEnv, RendererConfig } from '~/interfaces/services/renderer';
 import { ISidebarConfig } from '~/interfaces/sidebar-config';
 import { IUserUISettings } from '~/interfaces/user-ui-settings';
 import { PageModel, PageDocument } from '~/server/models/page';
@@ -61,7 +61,7 @@ import {
   useHackmdUri,
   useIsAclEnabled, useIsUserPage, useIsNotCreatable,
   useCsrfToken, useIsSearchScopeChildrenAsDefault, useCurrentPageId, useCurrentPathname,
-  useIsSlackConfigured, useRendererConfig, useEditingMarkdown,
+  useIsSlackConfigured, useGrowiHydratedEnv, useRendererConfig, useEditingMarkdown,
   useEditorConfig, useIsAllReplyShown, useIsUploadableFile, useIsUploadableImage,
 } from '../stores/context';
 
@@ -147,9 +147,7 @@ type Props = CommonProps & {
   // isMailerSetup: boolean,
   isAclEnabled: boolean,
   // hasSlackConfig: boolean,
-  // drawioUri: string,
   hackmdUri: string,
-  // noCdn: string,
   // highlightJsStyle: string,
   isAllReplyShown: boolean,
   // isContainerFluid: boolean,
@@ -161,6 +159,7 @@ type Props = CommonProps & {
   // isIndentSizeForced: boolean,
   disableLinkSharing: boolean,
 
+  growiHydratedEnv : GrowiHydratedEnv,
   rendererConfig: RendererConfig,
 
   // UI
@@ -220,6 +219,7 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
   // useIndentSize(props.adminPreferredIndentSize);
   useDisableLinkSharing(props.disableLinkSharing);
 
+  useGrowiHydratedEnv(props.growiHydratedEnv);
   useRendererConfig(props.rendererConfig);
   // useRendererSettings(props.rendererSettingsStr != null ? JSON.parse(props.rendererSettingsStr) : undefined);
   // useGrowiRendererConfig(props.growiRendererConfigStr != null ? JSON.parse(props.growiRendererConfigStr) : undefined);
@@ -515,9 +515,6 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
   // props.isMailerSetup = mailService.isMailerSetup;
   props.isAclEnabled = aclService.isAclEnabled();
   // props.hasSlackConfig = slackNotificationService.hasSlackConfig();
-  // props.drawioUri = configManager.getConfig('crowi', 'app:drawioUri');
-  props.hackmdUri = configManager.getConfig('crowi', 'app:hackmdUri');
-  // props.noCdn = configManager.getConfig('crowi', 'app:noCdn');
   // props.highlightJsStyle = configManager.getConfig('crowi', 'customize:highlightJsStyle');
   props.isAllReplyShown = configManager.getConfig('crowi', 'customize:isAllReplyShown');
   // props.isContainerFluid = configManager.getConfig('crowi', 'customize:isContainerFluid');
@@ -534,6 +531,14 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
   // props.adminPreferredIndentSize = configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize');
   // props.isIndentSizeForced = configManager.getConfig('markdown', 'markdown:isIndentSizeForced');
 
+  props.growiHydratedEnv = {
+    DRAWIO_URI: configManager.getConfig('crowi', 'app:drawioUri'),
+    HACKMD_URI: configManager.getConfig('crowi', 'app:hackmdUri'),
+    NO_CDN: configManager.getConfig('crowi', 'app:noCdn'),
+    GROWI_CLOUD_URI: configManager.getConfig('crowi', 'app:growiCloudUri'),
+    GROWI_APP_ID_FOR_GROWI_CLOUD: configManager.getConfig('crowi', 'app:growiAppIdForCloud'),
+  };
+
   props.rendererConfig = {
     isEnabledLinebreaks: configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks'),
     isEnabledLinebreaksInComments: configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments'),

+ 5 - 1
packages/app/src/stores/context.tsx

@@ -6,7 +6,7 @@ import useSWRImmutable from 'swr/immutable';
 import { SupportedActionType } from '~/interfaces/activity';
 import { EditorConfig } from '~/interfaces/editor-settings';
 // import { CustomWindow } from '~/interfaces/global';
-import { RendererConfig } from '~/interfaces/services/renderer';
+import { GrowiHydratedEnv, RendererConfig } from '~/interfaces/services/renderer';
 import { GrowiThemes } from '~/interfaces/theme';
 import InterceptorManager from '~/services/interceptor-manager';
 
@@ -231,6 +231,10 @@ export const useEditorConfig = (initialData?: EditorConfig): SWRResponse<EditorC
   return useStaticSWR<EditorConfig, Error>('editorConfig', initialData);
 };
 
+export const useGrowiHydratedEnv = (initialData?: GrowiHydratedEnv): SWRResponse<GrowiHydratedEnv, Error> => {
+  return useStaticSWR('growiHydratedEnv', initialData);
+};
+
 export const useRendererConfig = (initialData?: RendererConfig): SWRResponse<RendererConfig, any> => {
   return useStaticSWR('growiRendererConfig', initialData);
 };