pdf-preview-error.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. import PropTypes from 'prop-types'
  2. import { useTranslation, Trans } from 'react-i18next'
  3. import { memo, useCallback } from 'react'
  4. import { Button } from 'react-bootstrap'
  5. import PdfLogEntry from './pdf-log-entry'
  6. import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context'
  7. import { useStopOnFirstError } from '../../../shared/hooks/use-stop-on-first-error'
  8. import StopOnFirstErrorBadge from '../../../shared/components/stop-on-first-error-badge'
  9. function PdfPreviewError({ error }) {
  10. const { t } = useTranslation()
  11. const { startCompile } = useCompileContext()
  12. switch (error) {
  13. case 'rendering-error-expected':
  14. return (
  15. <PdfLogEntry
  16. headerTitle={t('pdf_rendering_error')}
  17. formattedContent={
  18. <>
  19. <Trans i18nKey="something_went_wrong_rendering_pdf_expected">
  20. <Button
  21. bsSize="xs"
  22. bsStyle="info"
  23. onClick={() => startCompile()}
  24. />
  25. </Trans>
  26. <br />
  27. <br />
  28. <Trans i18nKey="last_resort_trouble_shooting_guide">
  29. {
  30. // eslint-disable-next-line jsx-a11y/anchor-has-content
  31. <a
  32. href="/learn/how-to/Resolving_access%2C_loading%2C_and_display_problems"
  33. target="_blank"
  34. />
  35. }
  36. </Trans>
  37. </>
  38. }
  39. level="warning"
  40. />
  41. )
  42. case 'rendering-error':
  43. return (
  44. <ErrorLogEntry title={t('pdf_rendering_error')}>
  45. {t('something_went_wrong_rendering_pdf')}
  46. &nbsp;
  47. <Trans
  48. i18nKey="try_recompile_project_or_troubleshoot"
  49. components={[
  50. // eslint-disable-next-line react/jsx-key, jsx-a11y/anchor-has-content
  51. <a href="/learn/how-to/Resolving_access%2C_loading%2C_and_display_problems" />,
  52. ]}
  53. />
  54. </ErrorLogEntry>
  55. )
  56. case 'clsi-maintenance':
  57. return (
  58. <ErrorLogEntry title={t('server_error')}>
  59. {t('clsi_maintenance')}
  60. </ErrorLogEntry>
  61. )
  62. case 'clsi-unavailable':
  63. return (
  64. <ErrorLogEntry title={t('server_error')}>
  65. {t('clsi_unavailable')}
  66. </ErrorLogEntry>
  67. )
  68. case 'too-recently-compiled':
  69. return (
  70. <ErrorLogEntry title={t('server_error')}>
  71. {t('too_recently_compiled')}
  72. </ErrorLogEntry>
  73. )
  74. case 'terminated':
  75. return (
  76. <ErrorLogEntry title={t('terminated')}>
  77. {t('compile_terminated_by_user')}
  78. </ErrorLogEntry>
  79. )
  80. case 'rate-limited':
  81. return (
  82. <ErrorLogEntry title={t('pdf_compile_rate_limit_hit')}>
  83. {t('project_flagged_too_many_compiles')}
  84. </ErrorLogEntry>
  85. )
  86. case 'compile-in-progress':
  87. return (
  88. <ErrorLogEntry title={t('pdf_compile_in_progress_error')}>
  89. {t('pdf_compile_try_again')}
  90. </ErrorLogEntry>
  91. )
  92. case 'auto-compile-disabled':
  93. return (
  94. <ErrorLogEntry title={t('autocompile_disabled')}>
  95. {t('autocompile_disabled_reason')}
  96. </ErrorLogEntry>
  97. )
  98. case 'project-too-large':
  99. return (
  100. <ErrorLogEntry title={t('project_too_large')}>
  101. {t('project_too_much_editable_text')}
  102. </ErrorLogEntry>
  103. )
  104. case 'timedout':
  105. return <TimedOutLogEntry />
  106. case 'failure':
  107. return (
  108. <ErrorLogEntry title={t('no_pdf_error_title')}>
  109. {t('no_pdf_error_explanation')}
  110. <ul className="log-entry-formatted-content-list">
  111. <li>{t('no_pdf_error_reason_unrecoverable_error')}</li>
  112. <li>
  113. <Trans
  114. i18nKey="no_pdf_error_reason_no_content"
  115. components={{ code: <code /> }}
  116. />
  117. </li>
  118. <li>
  119. <Trans
  120. i18nKey="no_pdf_error_reason_output_pdf_already_exists"
  121. components={{ code: <code /> }}
  122. />
  123. </li>
  124. </ul>
  125. </ErrorLogEntry>
  126. )
  127. case 'clear-cache':
  128. return (
  129. <ErrorLogEntry title={t('server_error')}>
  130. {t('somthing_went_wrong_compiling')}
  131. </ErrorLogEntry>
  132. )
  133. case 'pdf-viewer-loading-error':
  134. return (
  135. <ErrorLogEntry title={t('pdf_rendering_error')}>
  136. <Trans
  137. i18nKey="something_went_wrong_loading_pdf_viewer"
  138. components={[
  139. <strong key="strong-" />,
  140. // eslint-disable-next-line jsx-a11y/anchor-has-content
  141. <a
  142. key="learn-link"
  143. target="_blank"
  144. href="/learn/how-to/Resolving_access%2C_loading%2C_and_display_problems"
  145. />,
  146. // eslint-disable-next-line jsx-a11y/anchor-has-content
  147. <a key="contact-link" target="_blank" href="/contact" />,
  148. ]}
  149. />
  150. </ErrorLogEntry>
  151. )
  152. case 'validation-problems':
  153. return null // handled elsewhere
  154. case 'error':
  155. default:
  156. return (
  157. <ErrorLogEntry title={t('server_error')}>
  158. {t('somthing_went_wrong_compiling')}
  159. </ErrorLogEntry>
  160. )
  161. }
  162. }
  163. PdfPreviewError.propTypes = {
  164. error: PropTypes.string.isRequired,
  165. }
  166. export default memo(PdfPreviewError)
  167. function ErrorLogEntry({ title, headerIcon, children }) {
  168. const { t } = useTranslation()
  169. return (
  170. <PdfLogEntry
  171. headerTitle={title}
  172. headerIcon={headerIcon}
  173. formattedContent={children}
  174. entryAriaLabel={t('compile_error_entry_description')}
  175. level="error"
  176. />
  177. )
  178. }
  179. ErrorLogEntry.propTypes = {
  180. title: PropTypes.string.isRequired,
  181. headerIcon: PropTypes.element,
  182. children: PropTypes.any.isRequired,
  183. }
  184. function TimedOutLogEntry() {
  185. const { t } = useTranslation()
  186. const { enableStopOnFirstError } = useStopOnFirstError({
  187. eventSource: 'timeout',
  188. })
  189. const { startCompile, lastCompileOptions, setAnimateCompileDropdownArrow } =
  190. useCompileContext()
  191. const handleEnableStopOnFirstErrorClick = useCallback(() => {
  192. enableStopOnFirstError()
  193. startCompile({ stopOnFirstError: true })
  194. setAnimateCompileDropdownArrow(true)
  195. }, [enableStopOnFirstError, startCompile, setAnimateCompileDropdownArrow])
  196. return (
  197. <ErrorLogEntry title={t('timedout')}>
  198. <p>{t('project_timed_out_intro')}</p>
  199. <ul>
  200. <li>
  201. <Trans
  202. i18nKey="project_timed_out_optimize_images"
  203. components={[
  204. // eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key
  205. <a href="https://www.overleaf.com/learn/how-to/Optimising_very_large_image_files" />,
  206. ]}
  207. />
  208. </li>
  209. <li>
  210. <Trans
  211. i18nKey="project_timed_out_fatal_error"
  212. components={[
  213. // eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key
  214. <a href="https://www.overleaf.com/learn/how-to/Why_do_I_keep_getting_the_compile_timeout_error_message%3F#Fatal_compile_errors_blocking_the_compilation" />,
  215. ]}
  216. />
  217. {!lastCompileOptions.stopOnFirstError && (
  218. <>
  219. {' '}
  220. <Trans
  221. i18nKey="project_timed_out_enable_stop_on_first_error"
  222. components={[
  223. // eslint-disable-next-line react/jsx-key
  224. <Button
  225. bsSize="xs"
  226. bsStyle="info"
  227. onClick={handleEnableStopOnFirstErrorClick}
  228. />,
  229. ]}
  230. />{' '}
  231. <StopOnFirstErrorBadge placement="bottom" />
  232. </>
  233. )}
  234. </li>
  235. </ul>
  236. <p>
  237. <Trans
  238. i18nKey="project_timed_out_learn_more"
  239. components={[
  240. // eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key
  241. <a href="https://www.overleaf.com/learn/how-to/Why_do_I_keep_getting_the_compile_timeout_error_message%3F" />,
  242. ]}
  243. />
  244. </p>
  245. </ErrorLogEntry>
  246. )
  247. }
  248. TimedOutLogEntry.propTypes = {}