preview-logs-pane-entry.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import PropTypes from 'prop-types'
  2. import classNames from 'classnames'
  3. import { useTranslation } from 'react-i18next'
  4. import useExpandCollapse from '../../../shared/hooks/use-expand-collapse'
  5. import Icon from '../../../shared/components/icon'
  6. import PreviewLogEntryHeader from './preview-log-entry-header'
  7. function PreviewLogsPaneEntry({
  8. headerTitle,
  9. headerIcon,
  10. rawContent,
  11. logType,
  12. formattedContent,
  13. extraInfoURL,
  14. level,
  15. sourceLocation,
  16. showSourceLocationLink = true,
  17. showCloseButton = false,
  18. entryAriaLabel = null,
  19. customClass,
  20. onSourceLocationClick,
  21. onClose,
  22. }) {
  23. const logEntryClasses = classNames('log-entry', customClass)
  24. function handleLogEntryLinkClick(e) {
  25. e.preventDefault()
  26. onSourceLocationClick(sourceLocation)
  27. }
  28. return (
  29. <div className={logEntryClasses} aria-label={entryAriaLabel}>
  30. <PreviewLogEntryHeader
  31. level={level}
  32. sourceLocation={sourceLocation}
  33. headerTitle={headerTitle}
  34. headerIcon={headerIcon}
  35. logType={logType}
  36. showSourceLocationLink={showSourceLocationLink}
  37. onSourceLocationClick={handleLogEntryLinkClick}
  38. showCloseButton={showCloseButton}
  39. onClose={onClose}
  40. />
  41. {rawContent || formattedContent ? (
  42. <PreviewLogEntryContent
  43. rawContent={rawContent}
  44. formattedContent={formattedContent}
  45. extraInfoURL={extraInfoURL}
  46. />
  47. ) : null}
  48. </div>
  49. )
  50. }
  51. function PreviewLogEntryContent({
  52. rawContent,
  53. formattedContent,
  54. extraInfoURL,
  55. }) {
  56. const {
  57. isExpanded,
  58. needsExpandCollapse,
  59. expandableProps,
  60. toggleProps,
  61. } = useExpandCollapse({
  62. collapsedSize: 150,
  63. })
  64. const buttonContainerClasses = classNames(
  65. 'log-entry-content-button-container',
  66. {
  67. 'log-entry-content-button-container-collapsed': !isExpanded,
  68. }
  69. )
  70. const { t } = useTranslation()
  71. return (
  72. <div className="log-entry-content">
  73. {formattedContent ? (
  74. <div className="log-entry-formatted-content">{formattedContent}</div>
  75. ) : null}
  76. {extraInfoURL ? (
  77. <div className="log-entry-content-link">
  78. <a href={extraInfoURL} target="_blank" rel="noopener">
  79. {t('log_hint_extra_info')}
  80. </a>
  81. </div>
  82. ) : null}
  83. {rawContent ? (
  84. <div className="log-entry-content-raw-container">
  85. <div {...expandableProps}>
  86. <pre className="log-entry-content-raw">{rawContent.trim()}</pre>
  87. </div>
  88. {needsExpandCollapse ? (
  89. <div className={buttonContainerClasses}>
  90. <button
  91. type="button"
  92. className="btn btn-xs btn-default log-entry-btn-expand-collapse"
  93. {...toggleProps}
  94. >
  95. {isExpanded ? (
  96. <>
  97. <Icon type="angle-up" /> {t('collapse')}
  98. </>
  99. ) : (
  100. <>
  101. <Icon type="angle-down" /> {t('expand')}
  102. </>
  103. )}
  104. </button>
  105. </div>
  106. ) : null}
  107. </div>
  108. ) : null}
  109. </div>
  110. )
  111. }
  112. PreviewLogEntryContent.propTypes = {
  113. rawContent: PropTypes.string,
  114. formattedContent: PropTypes.node,
  115. extraInfoURL: PropTypes.string,
  116. }
  117. PreviewLogsPaneEntry.propTypes = {
  118. sourceLocation: PreviewLogEntryHeader.propTypes.sourceLocation,
  119. headerTitle: PropTypes.string,
  120. headerIcon: PropTypes.element,
  121. rawContent: PropTypes.string,
  122. logType: PropTypes.string,
  123. formattedContent: PropTypes.node,
  124. extraInfoURL: PropTypes.string,
  125. level: PropTypes.oneOf(['error', 'warning', 'typesetting', 'raw', 'success'])
  126. .isRequired,
  127. customClass: PropTypes.string,
  128. showSourceLocationLink: PropTypes.bool,
  129. showCloseButton: PropTypes.bool,
  130. entryAriaLabel: PropTypes.string,
  131. onSourceLocationClick: PropTypes.func,
  132. onClose: PropTypes.func,
  133. }
  134. export default PreviewLogsPaneEntry