Przeglądaj źródła

typescriptize DrawioModal

kaori 3 lat temu
rodzic
commit
f2fc4647cb

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

@@ -26,14 +26,17 @@ import {
 import loggerFactory from '~/utils/logger';
 
 import RevisionRenderer from './Page/RevisionRenderer';
-import DrawioModal from './PageEditor/DrawioModal';
-
-
-// TODO: import dynamically
+import { DrawioModal } from './PageEditor/DrawioModal';
 // import MarkdownTable from '~/client/models/MarkdownTable';
 import mdu from './PageEditor/MarkdownDrawioUtil';
 import mtu from './PageEditor/MarkdownTableUtil';
 
+
+// TODO: import dynamically
+const GridEditModal = dynamic(() => import('./PageEditor/GridEditModal'), { ssr: false });
+// const HandsontableModal = dynamic(() => import('./PageEditor/HandsontableModal'), { ssr: false });
+const LinkEditModal = dynamic(() => import('./PageEditor/LinkEditModal'), { ssr: false });
+
 declare const globalEmitter: EventEmitter;
 
 const logger = loggerFactory('growi:Page');
@@ -172,11 +175,6 @@ class PageSubstance extends React.Component<PageSubstanceProps> {
     const { path } = page;
     const { _id: revisionId, body: markdown } = page.revision;
 
-    // const DrawioModal = dynamic(() => import('./PageEditor/DrawioModal'), { ssr: false });
-    const GridEditModal = dynamic(() => import('./PageEditor/GridEditModal'), { ssr: false });
-    // const HandsontableModal = dynamic(() => import('./PageEditor/HandsontableModal'), { ssr: false });
-    const LinkEditModal = dynamic(() => import('./PageEditor/LinkEditModal'), { ssr: false });
-
     return (
       <div className={`mb-5 ${isMobile ? 'page-mobile' : ''}`}>
 
@@ -189,7 +187,10 @@ 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>

+ 1 - 1
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';

+ 0 - 181
packages/app/src/components/PageEditor/DrawioModal.jsx

@@ -1,181 +0,0 @@
-import React from 'react';
-
-import i18next from 'i18next';
-import PropTypes from 'prop-types';
-import {
-  Modal,
-  ModalBody,
-} from 'reactstrap';
-
-import { getDiagramsNetLangCode } from '~/client/util/locale-utils';
-import { useGrowiHydratedEnv } from '~/stores/context';
-
-
-class DrawioModal extends React.PureComponent {
-
-  constructor(props) {
-    super(props);
-
-    this.state = {
-      show: false,
-      drawioMxFile: '',
-    };
-
-    this.headerColor = '#334455';
-    this.fontFamily = "Lato, -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif";
-
-    this.init = this.init.bind(this);
-    this.cancel = this.cancel.bind(this);
-    this.receiveFromDrawio = this.receiveFromDrawio.bind(this);
-  }
-
-  init(drawioMxFile) {
-    const initDrawioMxFile = drawioMxFile;
-    this.setState(
-      {
-        drawioMxFile: initDrawioMxFile,
-      },
-    );
-  }
-
-  show(drawioMxFile) {
-    this.init(drawioMxFile);
-
-    window.addEventListener('message', this.receiveFromDrawio);
-    this.setState({ show: true });
-  }
-
-  hide() {
-    this.setState({
-      show: false,
-    });
-  }
-
-  cancel() {
-    this.hide();
-  }
-
-  receiveFromDrawio(event) {
-    if (event.data === 'ready') {
-      event.source.postMessage(this.state.drawioMxFile, '*');
-      return;
-    }
-
-    if (event.data === '{"event":"configure"}') {
-      if (event.source == null) {
-        return;
-      }
-
-      // refs:
-      //  * https://desk.draw.io/support/solutions/articles/16000103852-how-to-customise-the-draw-io-interface
-      //  * https://desk.draw.io/support/solutions/articles/16000042544-how-does-embed-mode-work-
-      //  * https://desk.draw.io/support/solutions/articles/16000058316-how-to-configure-draw-io-
-      event.source.postMessage(JSON.stringify({
-        action: 'configure',
-        config: {
-          css: `
-          .geMenubarContainer { background-color: ${this.headerColor} !important; }
-          .geMenubar { background-color: ${this.headerColor} !important; }
-          .geEditor { font-family: ${this.fontFamily} !important; }
-          html td.mxPopupMenuItem {
-            font-family: ${this.fontFamily} !important;
-            font-size: 8pt !important;
-          }
-          `,
-          customFonts: ['Lato', 'Charter'],
-        },
-      }), '*');
-
-      return;
-    }
-
-    if (typeof event.data === 'string' && event.data.match(/mxfile/)) {
-      if (event.data.length > 0) {
-        const parser = new DOMParser();
-        const dom = parser.parseFromString(event.data, 'text/xml');
-        const value = dom.getElementsByTagName('diagram')[0].innerHTML;
-
-        if (this.props.onSave != null) {
-          this.props.onSave(value);
-        }
-      }
-
-      window.removeEventListener('message', this.receiveFromDrawio);
-      this.hide();
-
-      return;
-    }
-
-    if (typeof event.data === 'string' && event.data.length === 0) {
-      window.removeEventListener('message', this.receiveFromDrawio);
-      this.hide();
-
-      return;
-    }
-
-    // NOTHING DONE. (Receive unknown iframe message.)
-  }
-
-  get drawioURL() {
-    const { drawioUriEnv } = this.props;
-
-    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-
-    url.searchParams.append('spin', 1);
-    url.searchParams.append('embed', 1);
-    url.searchParams.append('lang', getDiagramsNetLangCode(i18next.language));
-    url.searchParams.append('ui', 'atlas');
-    url.searchParams.append('configure', 1);
-
-    return url;
-  }
-
-  render() {
-    return (
-      <Modal
-        isOpen={this.state.show}
-        toggle={this.cancel}
-        backdrop="static"
-        className="drawio-modal grw-body-only-modal-expanded"
-        size="xl"
-        keyboard={false}
-      >
-        <ModalBody className="p-0">
-          {/* Loading spinner */}
-          <div className="w-100 h-100 position-absolute d-flex">
-            <div className="mx-auto my-auto">
-              <i className="fa fa-3x fa-spinner fa-pulse mx-auto text-muted"></i>
-            </div>
-          </div>
-          {/* iframe */}
-          <div className="w-100 h-100 position-absolute d-flex">
-            { this.state.show && (
-              <iframe
-                src={this.drawioURL}
-                className="border-0 flex-grow-1"
-              >
-              </iframe>
-            ) }
-          </div>
-        </ModalBody>
-      </Modal>
-    );
-  }
-
-}
-
-DrawioModal.propTypes = {
-  onSave: PropTypes.func,
-  drawioUri:  PropTypes.string,
-};
-
-const DrawioModalFc = React.forwardRef((props, ref) => {
-  const { growiHydratedEnv } = useGrowiHydratedEnv();
-
-  return <DrawioModal onSave={props.onSave} drawioUri={growiHydratedEnv?.DRAWIO_URI} ref={ref} />;
-});
-
-
-export default DrawioModalFc;

+ 155 - 0
packages/app/src/components/PageEditor/DrawioModal.tsx

@@ -0,0 +1,155 @@
+import React, {
+  useState, useMemo,
+} from 'react';
+
+import i18next from 'i18next';
+import {
+  Modal,
+  ModalBody,
+} from 'reactstrap';
+
+import { getDiagramsNetLangCode } from '~/client/util/locale-utils';
+import { useGrowiHydratedEnv } from '~/stores/context';
+
+const headerColor = '#334455';
+const fontFamily = "Lato, -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif";
+
+
+type Props = {
+  onSave: (drawioData) => void,
+  drawioUri?: string,
+};
+
+export const DrawioModal = React.forwardRef((props: Props, ref: React.LegacyRef<Modal>): JSX.Element => {
+  const { data: growiHydratedEnv } = useGrowiHydratedEnv();
+  const [isShown, setIsShown] = useState(false);
+  const [drawioMxFile, setDrawioMxFile] = useState('');
+
+  const init = (drawioMxFile) => {
+    const initDrawioMxFile = drawioMxFile;
+    setDrawioMxFile(initDrawioMxFile);
+  };
+
+  const show = (drawioMxFile) => {
+    init(drawioMxFile);
+
+    window.addEventListener('message', receiveFromDrawio);
+    setIsShown(true);
+  };
+
+  const hide = () => {
+    setIsShown(false);
+  };
+
+  const cancel = () => {
+    hide();
+  };
+
+  const receiveFromDrawio = (event) => {
+    if (event.data === 'ready') {
+      event.source.postMessage(drawioMxFile, '*');
+      return;
+    }
+
+    if (event.data === '{"event":"configure"}') {
+      if (event.source == null) {
+        return;
+      }
+
+      // refs:
+      //  * https://desk.draw.io/support/solutions/articles/16000103852-how-to-customise-the-draw-io-interface
+      //  * https://desk.draw.io/support/solutions/articles/16000042544-how-does-embed-mode-work-
+      //  * https://desk.draw.io/support/solutions/articles/16000058316-how-to-configure-draw-io-
+      event.source.postMessage(JSON.stringify({
+        action: 'configure',
+        config: {
+          css: `
+          .geMenubarContainer { background-color: ${headerColor} !important; }
+          .geMenubar { background-color: ${headerColor} !important; }
+          .geEditor { font-family: ${fontFamily} !important; }
+          html td.mxPopupMenuItem {
+            font-family: ${fontFamily} !important;
+            font-size: 8pt !important;
+          }
+          `,
+          customFonts: ['Lato', 'Charter'],
+        },
+      }), '*');
+
+      return;
+    }
+
+    if (typeof event.data === 'string' && event.data.match(/mxfile/)) {
+      if (event.data.length > 0) {
+        const parser = new DOMParser();
+        const dom = parser.parseFromString(event.data, 'text/xml');
+        const drawioData = dom.getElementsByTagName('diagram')[0].innerHTML;
+
+        if (props.onSave != null) {
+          props.onSave(drawioData);
+        }
+      }
+
+      window.removeEventListener('message', receiveFromDrawio);
+      hide();
+
+      return;
+    }
+
+    if (typeof event.data === 'string' && event.data.length === 0) {
+      window.removeEventListener('message', receiveFromDrawio);
+      hide();
+
+      return;
+    }
+
+    // NOTHING DONE. (Receive unknown iframe message.)
+  };
+
+  const drawioUrl = useMemo(() => {
+    const drawioUri = growiHydratedEnv?.DRAWIO_URI || 'https://embed.diagrams.net/';
+    const url = new URL(drawioUri);
+
+    // refs: https://desk.draw.io/support/solutions/articles/16000042546-what-url-parameters-are-supported-
+    url.searchParams.append('spin', '1');
+    url.searchParams.append('embed', '1');
+    url.searchParams.append('lang', getDiagramsNetLangCode(i18next.language));
+    url.searchParams.append('ui', 'atlas');
+    url.searchParams.append('configure', '1');
+
+    return url.toString();
+  }, [growiHydratedEnv?.DRAWIO_URI]);
+
+  return (
+    <Modal
+      ref={ref}
+      isOpen={isShown}
+      toggle={cancel}
+      backdrop="static"
+      className="drawio-modal grw-body-only-modal-expanded"
+      size="xl"
+      keyboard={false}
+    >
+      <ModalBody className="p-0">
+        {/* Loading spinner */}
+        <div className="w-100 h-100 position-absolute d-flex">
+          <div className="mx-auto my-auto">
+            <i className="fa fa-3x fa-spinner fa-pulse mx-auto text-muted"></i>
+          </div>
+        </div>
+        {/* iframe */}
+        <div className="w-100 h-100 position-absolute d-flex">
+          { isShown && (
+            <iframe
+              src={drawioUrl}
+              className="border-0 flex-grow-1"
+            >
+            </iframe>
+          ) }
+        </div>
+      </ModalBody>
+    </Modal>
+  );
+});
+
+DrawioModal.displayName = 'DrawioModal';