preview-pane.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import React, { useState } from 'react'
  2. import PropTypes from 'prop-types'
  3. import PreviewToolbar from './preview-toolbar'
  4. import PreviewLogsPane from './preview-logs-pane'
  5. import PreviewFirstErrorPopUp from './preview-first-error-pop-up'
  6. import { useTranslation } from 'react-i18next'
  7. function PreviewPane({
  8. compilerState,
  9. onClearCache,
  10. onRecompile,
  11. onRecompileFromScratch,
  12. onRunSyntaxCheckNow,
  13. onSetAutoCompile,
  14. onSetDraftMode,
  15. onSetSyntaxCheck,
  16. onToggleLogs,
  17. onSetFullLayout,
  18. onSetSplitLayout,
  19. onStopCompilation,
  20. outputFiles,
  21. pdfDownloadUrl,
  22. onLogEntryLocationClick,
  23. showLogs,
  24. variantWithFirstErrorPopup = true,
  25. splitLayout
  26. }) {
  27. const { t } = useTranslation()
  28. const [lastCompileTimestamp, setLastCompileTimestamp] = useState(
  29. compilerState.lastCompileTimestamp
  30. )
  31. const [seenLogsForCurrentCompile, setSeenLogsForCurrentCompile] = useState(
  32. false
  33. )
  34. const [dismissedFirstErrorPopUp, setDismissedFirstErrorPopUp] = useState(
  35. false
  36. )
  37. if (lastCompileTimestamp < compilerState.lastCompileTimestamp) {
  38. setLastCompileTimestamp(compilerState.lastCompileTimestamp)
  39. setSeenLogsForCurrentCompile(false)
  40. }
  41. if (showLogs && !seenLogsForCurrentCompile) {
  42. setSeenLogsForCurrentCompile(true)
  43. }
  44. const nErrors =
  45. compilerState.logEntries && compilerState.logEntries.errors
  46. ? compilerState.logEntries.errors.length
  47. : 0
  48. const nWarnings =
  49. compilerState.logEntries && compilerState.logEntries.warnings
  50. ? compilerState.logEntries.warnings.length
  51. : 0
  52. const hasCLSIErrors =
  53. compilerState.errors &&
  54. Object.keys(compilerState.errors).length > 0 &&
  55. compilerState.compileFailed &&
  56. !compilerState.isCompiling
  57. const hasValidationIssues =
  58. compilerState.validationIssues &&
  59. Object.keys(compilerState.validationIssues).length > 0 &&
  60. compilerState.compileFailed &&
  61. !compilerState.isCompiling
  62. const showFirstErrorPopUp =
  63. variantWithFirstErrorPopup &&
  64. nErrors > 0 &&
  65. !seenLogsForCurrentCompile &&
  66. !dismissedFirstErrorPopUp &&
  67. !compilerState.isCompiling
  68. function handleFirstErrorPopUpClose() {
  69. setDismissedFirstErrorPopUp(true)
  70. }
  71. return (
  72. <>
  73. <PreviewToolbar
  74. compilerState={compilerState}
  75. logsState={{ nErrors, nWarnings }}
  76. showLogs={showLogs}
  77. onRecompile={onRecompile}
  78. onRecompileFromScratch={onRecompileFromScratch}
  79. onRunSyntaxCheckNow={onRunSyntaxCheckNow}
  80. onSetAutoCompile={onSetAutoCompile}
  81. onSetDraftMode={onSetDraftMode}
  82. onSetSyntaxCheck={onSetSyntaxCheck}
  83. onToggleLogs={onToggleLogs}
  84. onSetSplitLayout={onSetSplitLayout}
  85. onSetFullLayout={onSetFullLayout}
  86. onStopCompilation={onStopCompilation}
  87. outputFiles={outputFiles}
  88. pdfDownloadUrl={pdfDownloadUrl}
  89. splitLayout={splitLayout}
  90. />
  91. <span aria-live="polite" className="sr-only">
  92. {hasCLSIErrors ? t('compile_error_description') : ''}
  93. </span>
  94. <span aria-live="polite" className="sr-only">
  95. {hasValidationIssues ? t('validation_issue_description') : ''}
  96. </span>
  97. <span aria-live="polite" className="sr-only">
  98. {nErrors && !compilerState.isCompiling
  99. ? t('n_errors', { count: nErrors })
  100. : ''}
  101. </span>
  102. <span aria-live="polite" className="sr-only">
  103. {nWarnings && !compilerState.isCompiling
  104. ? t('n_warnings', { count: nWarnings })
  105. : ''}
  106. </span>
  107. {showFirstErrorPopUp ? (
  108. <PreviewFirstErrorPopUp
  109. logEntry={compilerState.logEntries.errors[0]}
  110. onGoToErrorLocation={onLogEntryLocationClick}
  111. onViewLogs={onToggleLogs}
  112. onClose={handleFirstErrorPopUpClose}
  113. />
  114. ) : null}
  115. {showLogs ? (
  116. <PreviewLogsPane
  117. logEntries={compilerState.logEntries}
  118. rawLog={compilerState.rawLog}
  119. validationIssues={compilerState.validationIssues}
  120. errors={compilerState.errors}
  121. autoCompileHasLintingError={compilerState.autoCompileHasLintingError}
  122. outputFiles={outputFiles}
  123. onLogEntryLocationClick={onLogEntryLocationClick}
  124. isClearingCache={compilerState.isClearingCache}
  125. isCompiling={compilerState.isCompiling}
  126. onClearCache={onClearCache}
  127. />
  128. ) : null}
  129. </>
  130. )
  131. }
  132. PreviewPane.propTypes = {
  133. compilerState: PropTypes.shape({
  134. autoCompileHasLintingError: PropTypes.bool,
  135. isAutoCompileOn: PropTypes.bool.isRequired,
  136. isCompiling: PropTypes.bool.isRequired,
  137. isDraftModeOn: PropTypes.bool.isRequired,
  138. isSyntaxCheckOn: PropTypes.bool.isRequired,
  139. isClearingCache: PropTypes.bool.isRequired,
  140. lastCompileTimestamp: PropTypes.number,
  141. logEntries: PropTypes.object,
  142. validationIssues: PropTypes.object,
  143. errors: PropTypes.object,
  144. rawLog: PropTypes.string,
  145. compileFailed: PropTypes.bool
  146. }),
  147. onClearCache: PropTypes.func.isRequired,
  148. onLogEntryLocationClick: PropTypes.func.isRequired,
  149. onRecompile: PropTypes.func.isRequired,
  150. onRecompileFromScratch: PropTypes.func.isRequired,
  151. onRunSyntaxCheckNow: PropTypes.func.isRequired,
  152. onSetAutoCompile: PropTypes.func.isRequired,
  153. onSetDraftMode: PropTypes.func.isRequired,
  154. onSetSyntaxCheck: PropTypes.func.isRequired,
  155. onSetSplitLayout: PropTypes.func.isRequired,
  156. onSetFullLayout: PropTypes.func.isRequired,
  157. onStopCompilation: PropTypes.func.isRequired,
  158. onToggleLogs: PropTypes.func.isRequired,
  159. outputFiles: PropTypes.array,
  160. pdfDownloadUrl: PropTypes.string,
  161. showLogs: PropTypes.bool.isRequired,
  162. variantWithFirstErrorPopup: PropTypes.bool,
  163. splitLayout: PropTypes.bool.isRequired
  164. }
  165. export default PreviewPane