DrawioModal.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. export const DrawioModal = (): JSX.Element => {
  30. const { data: drawioUri } = useDrawioUri();
  31. const { data: personalSettingsInfo } = usePersonalSettings();
  32. const { data: drawioModalData, close: closeDrawioModal } = useDrawioModal();
  33. const isOpened = drawioModalData?.isOpened ?? false;
  34. const drawioUriWithParams = useMemo(() => {
  35. if (drawioUri == null) {
  36. return undefined;
  37. }
  38. const url = new URL(drawioUri);
  39. // refs: https://desk.draw.io/support/solutions/articles/16000042546-what-url-parameters-are-supported-
  40. url.searchParams.append('spin', '1');
  41. url.searchParams.append('embed', '1');
  42. url.searchParams.append('lang', getDiagramsNetLangCode(personalSettingsInfo?.lang || 'en'));
  43. url.searchParams.append('ui', 'atlas');
  44. url.searchParams.append('configure', '1');
  45. return url;
  46. }, [drawioUri, personalSettingsInfo?.lang]);
  47. const drawioCommunicationHelper = useMemo(() => {
  48. if (drawioUri == null) {
  49. return undefined;
  50. }
  51. return new DrawioCommunicationHelper(
  52. drawioUri,
  53. drawioConfig,
  54. { onClose: closeDrawioModal, onSave: drawioModalData?.onSave },
  55. );
  56. }, [closeDrawioModal, drawioModalData?.onSave, drawioUri]);
  57. const receiveMessageHandler = useCallback((event: MessageEvent) => {
  58. if (drawioModalData == null) {
  59. return;
  60. }
  61. drawioCommunicationHelper?.onReceiveMessage(event, drawioModalData.drawioMxFile);
  62. }, [drawioCommunicationHelper, drawioModalData]);
  63. useEffect(() => {
  64. if (isOpened) {
  65. window.addEventListener('message', receiveMessageHandler);
  66. }
  67. else {
  68. window.removeEventListener('message', receiveMessageHandler);
  69. }
  70. // clean up
  71. return function() {
  72. window.removeEventListener('message', receiveMessageHandler);
  73. };
  74. }, [isOpened, receiveMessageHandler]);
  75. return (
  76. <Modal
  77. isOpen={isOpened}
  78. toggle={() => closeDrawioModal()}
  79. backdrop="static"
  80. className="drawio-modal grw-body-only-modal-expanded"
  81. size="xl"
  82. keyboard={false}
  83. >
  84. <ModalBody className="p-0">
  85. {/* Loading spinner */}
  86. <div className="w-100 h-100 position-absolute d-flex">
  87. <div className="mx-auto my-auto">
  88. <i className="fa fa-3x fa-spinner fa-pulse mx-auto text-muted"></i>
  89. </div>
  90. </div>
  91. {/* iframe */}
  92. { drawioUriWithParams != null && (
  93. <div className="w-100 h-100 position-absolute d-flex">
  94. { isOpened && (
  95. <iframe
  96. src={drawioUriWithParams.href}
  97. className="border-0 flex-grow-1"
  98. >
  99. </iframe>
  100. ) }
  101. </div>
  102. ) }
  103. </ModalBody>
  104. </Modal>
  105. );
  106. };