Drawio.tsx 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import React, {
  2. useCallback, useEffect, useMemo, useRef,
  3. } from 'react';
  4. import EventEmitter from 'events';
  5. import { useTranslation } from 'react-i18next';
  6. import { debounce } from 'throttle-debounce';
  7. import NotAvailableForGuest from './NotAvailableForGuest';
  8. declare let window: {
  9. globalEmitter: EventEmitter,
  10. GraphViewer: {
  11. createViewerForElement: (Element) => void,
  12. };
  13. };
  14. type Props = {
  15. drawioContent: string,
  16. rangeLineNumberOfMarkdown: { beginLineNumber: number, endLineNumber: number },
  17. isPreview?: boolean,
  18. }
  19. const Drawio = (props: Props): JSX.Element => {
  20. const { t } = useTranslation();
  21. const { drawioContent, rangeLineNumberOfMarkdown, isPreview } = props;
  22. // const { open: openDrawioModal } = useDrawioModalForPage();
  23. const drawioContainerRef = useRef<HTMLDivElement>(null);
  24. const editButtonClickHandler = useCallback(() => {
  25. const { beginLineNumber, endLineNumber } = rangeLineNumberOfMarkdown;
  26. window.globalEmitter.emit('launchDrawioModal', beginLineNumber, endLineNumber);
  27. }, [rangeLineNumberOfMarkdown]);
  28. const renderDrawio = useCallback(() => {
  29. if (drawioContainerRef.current == null) {
  30. return;
  31. }
  32. const mxgraphs = drawioContainerRef.current.getElementsByClassName('mxgraph');
  33. if (mxgraphs.length > 0) {
  34. // GROWI では、mxgraph element は最初のものをレンダリングする前提とする
  35. const div = mxgraphs[0];
  36. if (div != null) {
  37. div.innerHTML = '';
  38. window.GraphViewer.createViewerForElement(div);
  39. }
  40. }
  41. }, []);
  42. const renderDrawioWithDebounce = useMemo(() => debounce(200, renderDrawio), [renderDrawio]);
  43. const { GraphViewer } = window;
  44. useEffect(() => {
  45. if (GraphViewer == null) {
  46. return;
  47. }
  48. renderDrawioWithDebounce();
  49. }, [GraphViewer, renderDrawioWithDebounce]);
  50. return (
  51. <div className="editable-with-drawio position-relative">
  52. { !isPreview && (
  53. <NotAvailableForGuest>
  54. <button type="button" className="drawio-iframe-trigger position-absolute btn btn-outline-secondary" onClick={editButtonClickHandler}>
  55. <i className="icon-note mr-1"></i>{t('Edit')}
  56. </button>
  57. </NotAvailableForGuest>
  58. ) }
  59. <div
  60. className="drawio"
  61. style={
  62. {
  63. borderRadius: 3,
  64. border: '1px solid #d7d7d7',
  65. margin: '20px 0',
  66. }
  67. }
  68. ref={drawioContainerRef}
  69. // eslint-disable-next-line react/no-danger
  70. dangerouslySetInnerHTML={{ __html: drawioContent }}
  71. >
  72. </div>
  73. </div>
  74. );
  75. };
  76. export default Drawio;