DrawioModal.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import React, {
  2. useCallback,
  3. useEffect,
  4. useMemo,
  5. } from 'react';
  6. import {
  7. Modal,
  8. ModalBody,
  9. } from 'reactstrap';
  10. import { getDiagramsNetLangCode } from '~/client/util/locale-utils';
  11. import { useDrawioUri } from '~/stores/context';
  12. import { useDrawioModal } from '~/stores/modal';
  13. import { usePersonalSettings } from '~/stores/personal-settings';
  14. import { DrawioCommunicationHelper } from './DrawioCommunicationHelper';
  15. const headerColor = '#334455';
  16. const fontFamily = "Lato, -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif";
  17. const drawioConfig = {
  18. css: `
  19. .geMenubarContainer { background-color: ${headerColor} !important; }
  20. .geMenubar { background-color: ${headerColor} !important; }
  21. .geEditor { font-family: ${fontFamily} !important; }
  22. html td.mxPopupMenuItem {
  23. font-family: ${fontFamily} !important;
  24. font-size: 8pt !important;
  25. }
  26. `,
  27. customFonts: ['Lato', 'Charter'],
  28. };
  29. type Props = {
  30. // onSave: (drawioData) => void,
  31. };
  32. export const DrawioModal = (props: Props): JSX.Element => {
  33. const { data: drawioUri } = useDrawioUri();
  34. const { data: personalSettingsInfo } = usePersonalSettings();
  35. const { data: drawioModalData, close: closeDrawioModal } = useDrawioModal();
  36. const isOpened = drawioModalData?.isOpened ?? false;
  37. const drawioUriWithParams = useMemo(() => {
  38. if (drawioUri == null) {
  39. return undefined;
  40. }
  41. const url = new URL(drawioUri);
  42. // refs: https://desk.draw.io/support/solutions/articles/16000042546-what-url-parameters-are-supported-
  43. url.searchParams.append('spin', '1');
  44. url.searchParams.append('embed', '1');
  45. url.searchParams.append('lang', getDiagramsNetLangCode(personalSettingsInfo?.lang || 'en'));
  46. url.searchParams.append('ui', 'atlas');
  47. url.searchParams.append('configure', '1');
  48. return url;
  49. }, [drawioUri, personalSettingsInfo?.lang]);
  50. const drawioCommunicationHelper = useMemo(() => {
  51. if (drawioUri == null) {
  52. return undefined;
  53. }
  54. return new DrawioCommunicationHelper(
  55. drawioUri,
  56. drawioConfig,
  57. { onClose: closeDrawioModal },
  58. );
  59. }, [closeDrawioModal, drawioUri]);
  60. const receiveMessageHandler = useCallback((event: MessageEvent) => {
  61. if (drawioModalData == null) {
  62. return;
  63. }
  64. drawioCommunicationHelper?.onReceiveMessage(event, drawioModalData.drawioMxFile);
  65. }, [drawioCommunicationHelper, drawioModalData]);
  66. useEffect(() => {
  67. if (isOpened) {
  68. window.addEventListener('message', receiveMessageHandler);
  69. }
  70. else {
  71. window.removeEventListener('message', receiveMessageHandler);
  72. }
  73. // clean up
  74. return function() {
  75. window.removeEventListener('message', receiveMessageHandler);
  76. };
  77. }, [isOpened, receiveMessageHandler]);
  78. return (
  79. <Modal
  80. isOpen={isOpened}
  81. toggle={() => closeDrawioModal()}
  82. backdrop="static"
  83. className="drawio-modal grw-body-only-modal-expanded"
  84. size="xl"
  85. keyboard={false}
  86. >
  87. <ModalBody className="p-0">
  88. {/* Loading spinner */}
  89. <div className="w-100 h-100 position-absolute d-flex">
  90. <div className="mx-auto my-auto">
  91. <i className="fa fa-3x fa-spinner fa-pulse mx-auto text-muted"></i>
  92. </div>
  93. </div>
  94. {/* iframe */}
  95. { drawioUriWithParams != null && (
  96. <div className="w-100 h-100 position-absolute d-flex">
  97. { isOpened && (
  98. <iframe
  99. src={drawioUriWithParams.href}
  100. className="border-0 flex-grow-1"
  101. >
  102. </iframe>
  103. ) }
  104. </div>
  105. ) }
  106. </ModalBody>
  107. </Modal>
  108. );
  109. };