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

impl launchDrawioModal with EventEmitter

Yuki Takei 3 лет назад
Родитель
Сommit
7b7b7d78a7

+ 0 - 10
packages/app/src/client/services/AppContainer.js

@@ -180,14 +180,4 @@ export default class AppContainer extends Container {
     return renderer;
   }
 
-  launchDrawioModal(componentKind, beginLineNumber, endLineNumber) {
-    let targetComponent;
-    switch (componentKind) {
-      case 'page':
-        targetComponent = this.getComponentInstance('Page');
-        break;
-    }
-    targetComponent.launchDrawioModal(beginLineNumber, endLineNumber);
-  }
-
 }

+ 0 - 108
packages/app/src/components/Drawio.jsx

@@ -1,108 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-
-import { debounce } from 'throttle-debounce';
-
-import { withTranslation } from 'react-i18next';
-
-import AppContainer from '~/client/services/AppContainer';
-
-import { withUnstatedContainers } from './UnstatedUtils';
-
-import NotAvailableForGuest from './NotAvailableForGuest';
-
-class Drawio extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    this.drawioContainer = React.createRef();
-
-    this.style = {
-      borderRadius: 3,
-      border: '1px solid #d7d7d7',
-      margin: '20px 0',
-    };
-
-    this.isPreview = this.props.isPreview;
-    this.drawioContent = this.props.drawioContent;
-
-    this.onEdit = this.onEdit.bind(this);
-
-    // create debounced method for rendering Drawio
-    this.renderDrawioWithDebounce = debounce(200, this.renderDrawio);
-  }
-
-  onEdit() {
-    const { appContainer, rangeLineNumberOfMarkdown } = this.props;
-    const { beginLineNumber, endLineNumber } = rangeLineNumberOfMarkdown;
-    appContainer.launchDrawioModal('page', beginLineNumber, endLineNumber);
-  }
-
-  componentDidMount() {
-    const DrawioViewer = window.GraphViewer;
-    if (DrawioViewer != null) {
-      this.renderDrawio();
-    }
-    else {
-      this.renderDrawioWithDebounce();
-    }
-  }
-
-  renderDrawio() {
-    const DrawioViewer = window.GraphViewer;
-    if (DrawioViewer != null) {
-      const mxgraphs = this.drawioContainer.getElementsByClassName('mxgraph');
-      if (mxgraphs.length > 0) {
-        // GROWI では、mxgraph element は最初のものをレンダリングする前提とする
-        const div = mxgraphs[0];
-
-        if (div != null) {
-          div.innerHTML = '';
-          DrawioViewer.createViewerForElement(div);
-        }
-      }
-    }
-    else {
-      this.renderDrawioWithDebounce();
-    }
-  }
-
-  renderContents() {
-    return this.drawioContent;
-  }
-
-  render() {
-    return (
-      <div className="editable-with-drawio position-relative">
-        { !this.isPreview && (
-          <NotAvailableForGuest>
-            <button type="button" className="drawio-iframe-trigger position-absolute btn btn-outline-secondary" onClick={this.onEdit}>
-              <i className="icon-note mr-1"></i>{this.props.t('Edit')}
-            </button>
-          </NotAvailableForGuest>
-        ) }
-        <div
-          className="drawio"
-          style={this.style}
-          ref={(c) => { this.drawioContainer = c }}
-          // eslint-disable-next-line react/no-danger
-          dangerouslySetInnerHTML={{ __html: this.renderContents() }}
-        >
-        </div>
-      </div>
-    );
-  }
-
-}
-
-Drawio.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.object.isRequired,
-
-  drawioContent: PropTypes.any.isRequired,
-  isPreview: PropTypes.bool,
-  rangeLineNumberOfMarkdown: PropTypes.object.isRequired,
-};
-
-export default withTranslation()(withUnstatedContainers(Drawio, [AppContainer]));

+ 97 - 0
packages/app/src/components/Drawio.tsx

@@ -0,0 +1,97 @@
+import React, {
+  useCallback, useEffect, useMemo, useRef,
+} from 'react';
+
+import EventEmitter from 'events';
+
+import { useTranslation } from 'react-i18next';
+import { debounce } from 'throttle-debounce';
+
+import NotAvailableForGuest from './NotAvailableForGuest';
+
+
+declare let window: {
+  globalEmitter: EventEmitter,
+  GraphViewer: {
+    createViewerForElement: (Element) => void,
+  };
+};
+
+type Props = {
+  drawioContent: string,
+  rangeLineNumberOfMarkdown: { beginLineNumber: number, endLineNumber: number },
+  isPreview?: boolean,
+}
+
+const Drawio = (props: Props): JSX.Element => {
+
+  const { t } = useTranslation();
+
+  const { drawioContent, rangeLineNumberOfMarkdown, isPreview } = props;
+
+  // const { open: openDrawioModal } = useDrawioModalForPage();
+
+  const drawioContainerRef = useRef<HTMLDivElement>(null);
+
+  const editButtonClickHandler = useCallback(() => {
+    const { beginLineNumber, endLineNumber } = rangeLineNumberOfMarkdown;
+    window.globalEmitter.emit('launchDrawioModal', beginLineNumber, endLineNumber);
+  }, [rangeLineNumberOfMarkdown]);
+
+  const renderDrawio = useCallback(() => {
+    if (drawioContainerRef.current == null) {
+      return;
+    }
+
+    const mxgraphs = drawioContainerRef.current.getElementsByClassName('mxgraph');
+    if (mxgraphs.length > 0) {
+      // GROWI では、mxgraph element は最初のものをレンダリングする前提とする
+      const div = mxgraphs[0];
+
+      if (div != null) {
+        div.innerHTML = '';
+        window.GraphViewer.createViewerForElement(div);
+      }
+    }
+  }, []);
+
+  const renderDrawioWithDebounce = useMemo(() => debounce(200, renderDrawio), [renderDrawio]);
+
+  const { GraphViewer } = window;
+  useEffect(() => {
+    if (GraphViewer == null) {
+      return;
+    }
+
+    renderDrawioWithDebounce();
+  }, [GraphViewer, renderDrawioWithDebounce]);
+
+  return (
+    <div className="editable-with-drawio position-relative">
+      { !isPreview && (
+        <NotAvailableForGuest>
+          <button type="button" className="drawio-iframe-trigger position-absolute btn btn-outline-secondary" onClick={editButtonClickHandler}>
+            <i className="icon-note mr-1"></i>{t('Edit')}
+          </button>
+        </NotAvailableForGuest>
+      ) }
+      <div
+        className="drawio"
+        style={
+          {
+            borderRadius: 3,
+            border: '1px solid #d7d7d7',
+            margin: '20px 0',
+          }
+        }
+        ref={drawioContainerRef}
+        // eslint-disable-next-line react/no-danger
+        dangerouslySetInnerHTML={{ __html: drawioContent }}
+      >
+      </div>
+    </div>
+  );
+
+};
+
+export default Drawio;

+ 16 - 5
packages/app/src/components/Page.jsx

@@ -49,10 +49,6 @@ class Page extends React.Component {
     this.saveHandlerForDrawioModal = this.saveHandlerForDrawioModal.bind(this);
   }
 
-  componentWillMount() {
-    this.props.appContainer.registerComponentInstance('Page', this);
-  }
-
   /**
    * launch HandsontableModal with data specified by arguments
    * @param beginLineNumber
@@ -199,6 +195,21 @@ const PageWrapper = (props) => {
 
   const pageRef = useRef(null);
 
+  // set handler to open DrawioModal
+  useEffect(() => {
+    const handler = (beginLineNumber, endLineNumber) => {
+      if (pageRef?.current != null) {
+        pageRef.current.launchDrawioModal(beginLineNumber, endLineNumber);
+      }
+    };
+    window.globalEmitter.on('launchDrawioModal', handler);
+
+    return function cleanup() {
+      window.globalEmitter.removeListener('launchDrawioModal', handler);
+    };
+  }, []);
+
+  // set handler to open HandsontableModal
   useEffect(() => {
     const handler = (beginLineNumber, endLineNumber) => {
       if (pageRef?.current != null) {
@@ -210,7 +221,7 @@ const PageWrapper = (props) => {
     return function cleanup() {
       window.globalEmitter.removeListener('launchHandsontableModal', handler);
     };
-  });
+  }, []);
 
   if (currentPagePath == null || editorMode == null || isGuestUser == null) {
     return null;