preview-pane.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import { 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. nErrors={nErrors}
  111. onGoToErrorLocation={onLogEntryLocationClick}
  112. onViewLogs={onToggleLogs}
  113. onClose={handleFirstErrorPopUpClose}
  114. />
  115. ) : null}
  116. {showLogs ? (
  117. <PreviewLogsPane
  118. logEntries={compilerState.logEntries}
  119. rawLog={compilerState.rawLog}
  120. validationIssues={compilerState.validationIssues}
  121. errors={compilerState.errors}
  122. autoCompileHasLintingError={compilerState.autoCompileHasLintingError}
  123. outputFiles={outputFiles}
  124. onLogEntryLocationClick={onLogEntryLocationClick}
  125. isClearingCache={compilerState.isClearingCache}
  126. isCompiling={compilerState.isCompiling}
  127. variantWithFirstErrorPopup={variantWithFirstErrorPopup}
  128. onClearCache={onClearCache}
  129. />
  130. ) : null}
  131. </>
  132. )
  133. }
  134. PreviewPane.propTypes = {
  135. compilerState: PropTypes.shape({
  136. autoCompileHasLintingError: PropTypes.bool,
  137. isAutoCompileOn: PropTypes.bool.isRequired,
  138. isCompiling: PropTypes.bool.isRequired,
  139. isDraftModeOn: PropTypes.bool.isRequired,
  140. isSyntaxCheckOn: PropTypes.bool.isRequired,
  141. isClearingCache: PropTypes.bool.isRequired,
  142. lastCompileTimestamp: PropTypes.number,
  143. logEntries: PropTypes.object,
  144. validationIssues: PropTypes.object,
  145. errors: PropTypes.object,
  146. rawLog: PropTypes.string,
  147. compileFailed: PropTypes.bool,
  148. }),
  149. onClearCache: PropTypes.func.isRequired,
  150. onLogEntryLocationClick: PropTypes.func.isRequired,
  151. onRecompile: PropTypes.func.isRequired,
  152. onRecompileFromScratch: PropTypes.func.isRequired,
  153. onRunSyntaxCheckNow: PropTypes.func.isRequired,
  154. onSetAutoCompile: PropTypes.func.isRequired,
  155. onSetDraftMode: PropTypes.func.isRequired,
  156. onSetSyntaxCheck: PropTypes.func.isRequired,
  157. onSetSplitLayout: PropTypes.func.isRequired,
  158. onSetFullLayout: PropTypes.func.isRequired,
  159. onStopCompilation: PropTypes.func.isRequired,
  160. onToggleLogs: PropTypes.func.isRequired,
  161. outputFiles: PropTypes.array,
  162. pdfDownloadUrl: PropTypes.string,
  163. showLogs: PropTypes.bool.isRequired,
  164. variantWithFirstErrorPopup: PropTypes.bool,
  165. splitLayout: PropTypes.bool.isRequired,
  166. }
  167. export default PreviewPane