preview-pane.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. splitLayout
  25. }) {
  26. const { t } = useTranslation()
  27. const [lastCompileTimestamp, setLastCompileTimestamp] = useState(
  28. compilerState.lastCompileTimestamp
  29. )
  30. const [seenLogsForCurrentCompile, setSeenLogsForCurrentCompile] = useState(
  31. false
  32. )
  33. const [dismissedFirstErrorPopUp, setDismissedFirstErrorPopUp] = useState(
  34. false
  35. )
  36. if (lastCompileTimestamp < compilerState.lastCompileTimestamp) {
  37. setLastCompileTimestamp(compilerState.lastCompileTimestamp)
  38. setSeenLogsForCurrentCompile(false)
  39. }
  40. if (showLogs && !seenLogsForCurrentCompile) {
  41. setSeenLogsForCurrentCompile(true)
  42. }
  43. const nErrors =
  44. compilerState.logEntries && compilerState.logEntries.errors
  45. ? compilerState.logEntries.errors.length
  46. : 0
  47. const nWarnings =
  48. compilerState.logEntries && compilerState.logEntries.warnings
  49. ? compilerState.logEntries.warnings.length
  50. : 0
  51. const nLogEntries =
  52. compilerState.logEntries && compilerState.logEntries.all
  53. ? compilerState.logEntries.all.length
  54. : 0
  55. const hasCLSIErrors =
  56. compilerState.errors &&
  57. Object.keys(compilerState.errors).length > 0 &&
  58. compilerState.compileFailed &&
  59. !compilerState.isCompiling
  60. const hasValidationIssues =
  61. compilerState.validationIssues &&
  62. Object.keys(compilerState.validationIssues).length > 0 &&
  63. compilerState.compileFailed &&
  64. !compilerState.isCompiling
  65. const showFirstErrorPopUp =
  66. nErrors > 0 &&
  67. !seenLogsForCurrentCompile &&
  68. !dismissedFirstErrorPopUp &&
  69. !compilerState.isCompiling
  70. function handleFirstErrorPopUpClose() {
  71. setDismissedFirstErrorPopUp(true)
  72. }
  73. return (
  74. <>
  75. <PreviewToolbar
  76. compilerState={compilerState}
  77. logsState={{ nErrors, nWarnings, nLogEntries }}
  78. showLogs={showLogs}
  79. onRecompile={onRecompile}
  80. onRecompileFromScratch={onRecompileFromScratch}
  81. onRunSyntaxCheckNow={onRunSyntaxCheckNow}
  82. onSetAutoCompile={onSetAutoCompile}
  83. onSetDraftMode={onSetDraftMode}
  84. onSetSyntaxCheck={onSetSyntaxCheck}
  85. onToggleLogs={onToggleLogs}
  86. onSetSplitLayout={onSetSplitLayout}
  87. onSetFullLayout={onSetFullLayout}
  88. onStopCompilation={onStopCompilation}
  89. outputFiles={outputFiles}
  90. pdfDownloadUrl={pdfDownloadUrl}
  91. splitLayout={splitLayout}
  92. />
  93. <span aria-live="polite" className="sr-only">
  94. {hasCLSIErrors ? t('compile_error_description') : ''}
  95. </span>
  96. <span aria-live="polite" className="sr-only">
  97. {hasValidationIssues ? t('validation_issue_description') : ''}
  98. </span>
  99. <span aria-live="polite" className="sr-only">
  100. {nErrors && !compilerState.isCompiling
  101. ? t('n_errors', { count: nErrors })
  102. : ''}
  103. </span>
  104. <span aria-live="polite" className="sr-only">
  105. {nWarnings && !compilerState.isCompiling
  106. ? t('n_warnings', { count: nWarnings })
  107. : ''}
  108. </span>
  109. {showFirstErrorPopUp ? (
  110. <PreviewFirstErrorPopUp
  111. logEntry={compilerState.logEntries.errors[0]}
  112. onGoToErrorLocation={onLogEntryLocationClick}
  113. onViewLogs={onToggleLogs}
  114. onClose={handleFirstErrorPopUpClose}
  115. />
  116. ) : null}
  117. {showLogs ? (
  118. <PreviewLogsPane
  119. logEntries={compilerState.logEntries}
  120. rawLog={compilerState.rawLog}
  121. validationIssues={compilerState.validationIssues}
  122. errors={compilerState.errors}
  123. outputFiles={outputFiles}
  124. onLogEntryLocationClick={onLogEntryLocationClick}
  125. isClearingCache={compilerState.isClearingCache}
  126. isCompiling={compilerState.isCompiling}
  127. onClearCache={onClearCache}
  128. />
  129. ) : null}
  130. </>
  131. )
  132. }
  133. PreviewPane.propTypes = {
  134. compilerState: PropTypes.shape({
  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. splitLayout: PropTypes.bool.isRequired
  163. }
  164. export default PreviewPane