Modal.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { Spin, Skeleton, Modal as AntModal } from 'antd';
  2. import React, { FC, ReactNode, useState } from 'react';
  3. import { ErrorBoundary } from 'react-error-boundary';
  4. import { ComponentError } from '../ComponentError/ComponentError';
  5. import styles from './Modal.module.scss';
  6. export type ModalProps = {
  7. title: string;
  8. url?: string;
  9. open: boolean;
  10. handleOk?: () => void;
  11. handleCancel?: () => void;
  12. afterClose?: () => void;
  13. children?: ReactNode;
  14. height?: string;
  15. width?: string;
  16. };
  17. export const Modal: FC<ModalProps> = ({
  18. title,
  19. url,
  20. open,
  21. handleOk,
  22. handleCancel,
  23. afterClose,
  24. height,
  25. width,
  26. children,
  27. }) => {
  28. const [loading, setLoading] = useState(!!url);
  29. let defaultHeight = '100%';
  30. let defaultWidth = '520px';
  31. if (url) {
  32. defaultHeight = '70vh';
  33. defaultWidth = '900px';
  34. }
  35. const modalContentBodyStyle = {
  36. padding: '0px',
  37. minHeight: height,
  38. height: height ?? defaultHeight,
  39. };
  40. const iframe = url && (
  41. <iframe
  42. title={title}
  43. src={url}
  44. width="100%"
  45. height="100%"
  46. sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
  47. frameBorder="0"
  48. allowFullScreen
  49. style={{ display: 'block' }}
  50. // eslint-disable-next-line react/no-unknown-property
  51. onLoad={() => setLoading(false)}
  52. />
  53. );
  54. const iframeDisplayStyle = loading ? 'none' : 'inline';
  55. return (
  56. <AntModal
  57. title={title}
  58. open={open}
  59. onOk={handleOk}
  60. onCancel={handleCancel}
  61. afterClose={afterClose}
  62. bodyStyle={modalContentBodyStyle}
  63. width={width ?? defaultWidth}
  64. zIndex={999}
  65. footer={null}
  66. centered
  67. destroyOnClose
  68. >
  69. <ErrorBoundary
  70. // eslint-disable-next-line react/no-unstable-nested-components
  71. fallbackRender={({ error, resetErrorBoundary }) => (
  72. <ComponentError
  73. componentName="Modal"
  74. message={error.message}
  75. retryFunction={resetErrorBoundary}
  76. />
  77. )}
  78. >
  79. <div id="modal-container" style={{ height: '100%' }}>
  80. {loading && (
  81. <Skeleton active={loading} style={{ padding: '10px' }} paragraph={{ rows: 10 }} />
  82. )}
  83. {iframe && <div style={{ display: iframeDisplayStyle }}>{iframe}</div>}
  84. {children && <div className={styles.content}>{children}</div>}
  85. {loading && <Spin className={styles.spinner} spinning={loading} size="large" />}
  86. </div>
  87. </ErrorBoundary>
  88. </AntModal>
  89. );
  90. };
  91. export default Modal;
  92. Modal.defaultProps = {
  93. url: undefined,
  94. children: undefined,
  95. handleOk: undefined,
  96. handleCancel: undefined,
  97. afterClose: undefined,
  98. };