Drawio.tsx 2.5 KB

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