pdf-preview-error.jsx 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. import PropTypes from 'prop-types'
  2. import { useTranslation, Trans } from 'react-i18next'
  3. import { memo, useCallback } from 'react'
  4. import OLButton from '@/features/ui/components/ol/ol-button'
  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 getMeta from '../../../utils/meta'
  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
  20. i18nKey="something_went_wrong_rendering_pdf_expected"
  21. components={[
  22. // eslint-disable-next-line react/jsx-key
  23. <OLButton
  24. variant="info"
  25. size="sm"
  26. bs3Props={{ bsSize: 'xsmall' }}
  27. onClick={() => startCompile()}
  28. />,
  29. ]}
  30. />
  31. <br />
  32. <br />
  33. <Trans
  34. i18nKey="last_resort_trouble_shooting_guide"
  35. components={[
  36. // eslint-disable-next-line jsx-a11y/anchor-has-content
  37. <a
  38. href="/learn/how-to/Resolving_access%2C_loading%2C_and_display_problems"
  39. target="_blank"
  40. key="troubleshooting-link"
  41. />,
  42. ]}
  43. />
  44. </>
  45. }
  46. level="warning"
  47. />
  48. )
  49. case 'rendering-error':
  50. return (
  51. <ErrorLogEntry title={t('pdf_rendering_error')}>
  52. {t('something_went_wrong_rendering_pdf')}
  53. &nbsp;
  54. <Trans
  55. i18nKey="try_recompile_project_or_troubleshoot"
  56. components={[
  57. // eslint-disable-next-line jsx-a11y/anchor-has-content
  58. <a
  59. href="/learn/how-to/Resolving_access%2C_loading%2C_and_display_problems"
  60. target="_blank"
  61. key="troubleshooting-link"
  62. />,
  63. ]}
  64. />
  65. {getMeta('ol-compilesUserContentDomain') && (
  66. <>
  67. <br />
  68. <br />
  69. <Trans
  70. i18nKey="new_compile_domain_notice"
  71. values={{
  72. compilesUserContentDomain: new URL(
  73. getMeta('ol-compilesUserContentDomain')
  74. ).hostname,
  75. }}
  76. shouldUnescape
  77. tOptions={{ interpolation: { escapeValue: true } }}
  78. components={[
  79. <code key="domain" />,
  80. /* eslint-disable-next-line jsx-a11y/anchor-has-content */
  81. <a
  82. href="/learn/how-to/Resolving_access%2C_loading%2C_and_display_problems"
  83. target="_blank"
  84. key="troubleshooting-link"
  85. />,
  86. ]}
  87. />
  88. </>
  89. )}
  90. </ErrorLogEntry>
  91. )
  92. case 'clsi-maintenance':
  93. return (
  94. <ErrorLogEntry title={t('server_error')}>
  95. {t('clsi_maintenance')}
  96. </ErrorLogEntry>
  97. )
  98. case 'clsi-unavailable':
  99. return (
  100. <ErrorLogEntry title={t('server_error')}>
  101. {t('clsi_unavailable')}
  102. </ErrorLogEntry>
  103. )
  104. case 'too-recently-compiled':
  105. return (
  106. <ErrorLogEntry title={t('server_error')}>
  107. {t('too_recently_compiled')}
  108. </ErrorLogEntry>
  109. )
  110. case 'terminated':
  111. return (
  112. <ErrorLogEntry title={t('terminated')}>
  113. {t('compile_terminated_by_user')}
  114. </ErrorLogEntry>
  115. )
  116. case 'rate-limited':
  117. return (
  118. <ErrorLogEntry title={t('pdf_compile_rate_limit_hit')}>
  119. {t('project_flagged_too_many_compiles')}
  120. </ErrorLogEntry>
  121. )
  122. case 'compile-in-progress':
  123. return (
  124. <ErrorLogEntry title={t('pdf_compile_in_progress_error')}>
  125. {t('pdf_compile_try_again')}
  126. </ErrorLogEntry>
  127. )
  128. case 'autocompile-disabled':
  129. return (
  130. <ErrorLogEntry title={t('autocompile_disabled')}>
  131. {t('autocompile_disabled_reason')}
  132. </ErrorLogEntry>
  133. )
  134. case 'project-too-large':
  135. return (
  136. <ErrorLogEntry title={t('project_too_large')}>
  137. {t('project_too_much_editable_text')}
  138. </ErrorLogEntry>
  139. )
  140. case 'timedout':
  141. return <TimedOutLogEntry />
  142. case 'failure':
  143. return (
  144. <ErrorLogEntry title={t('no_pdf_error_title')}>
  145. {t('no_pdf_error_explanation')}
  146. <ul className="my-1 ps-3">
  147. <li>{t('no_pdf_error_reason_unrecoverable_error')}</li>
  148. <li>
  149. <Trans
  150. i18nKey="no_pdf_error_reason_no_content"
  151. components={{ code: <code /> }}
  152. />
  153. </li>
  154. <li>
  155. <Trans
  156. i18nKey="no_pdf_error_reason_output_pdf_already_exists"
  157. components={{ code: <code /> }}
  158. />
  159. </li>
  160. </ul>
  161. </ErrorLogEntry>
  162. )
  163. case 'clear-cache':
  164. return (
  165. <ErrorLogEntry title={t('server_error')}>
  166. {t('somthing_went_wrong_compiling')}
  167. </ErrorLogEntry>
  168. )
  169. case 'pdf-viewer-loading-error':
  170. return (
  171. <ErrorLogEntry title={t('pdf_rendering_error')}>
  172. <Trans
  173. i18nKey="something_went_wrong_loading_pdf_viewer"
  174. components={[
  175. <strong key="strong-" />,
  176. // eslint-disable-next-line jsx-a11y/anchor-has-content
  177. <a
  178. href="/learn/how-to/Resolving_access%2C_loading%2C_and_display_problems"
  179. target="_blank"
  180. key="troubleshooting-link"
  181. />,
  182. // eslint-disable-next-line jsx-a11y/anchor-has-content
  183. <a key="contact-link" target="_blank" href="/contact" />,
  184. ]}
  185. />
  186. </ErrorLogEntry>
  187. )
  188. case 'validation-problems':
  189. return null // handled elsewhere
  190. case 'error':
  191. default:
  192. return (
  193. <ErrorLogEntry title={t('server_error')}>
  194. {t('somthing_went_wrong_compiling')}
  195. </ErrorLogEntry>
  196. )
  197. }
  198. }
  199. PdfPreviewError.propTypes = {
  200. error: PropTypes.string.isRequired,
  201. }
  202. export default memo(PdfPreviewError)
  203. function ErrorLogEntry({ title, headerIcon, children }) {
  204. const { t } = useTranslation()
  205. return (
  206. <PdfLogEntry
  207. headerTitle={title}
  208. headerIcon={headerIcon}
  209. formattedContent={children}
  210. entryAriaLabel={t('compile_error_entry_description')}
  211. level="error"
  212. />
  213. )
  214. }
  215. ErrorLogEntry.propTypes = {
  216. title: PropTypes.string.isRequired,
  217. headerIcon: PropTypes.element,
  218. children: PropTypes.any.isRequired,
  219. }
  220. function TimedOutLogEntry() {
  221. const { t } = useTranslation()
  222. const { enableStopOnFirstError } = useStopOnFirstError({
  223. eventSource: 'timeout',
  224. })
  225. const { startCompile, lastCompileOptions, setAnimateCompileDropdownArrow } =
  226. useCompileContext()
  227. const handleEnableStopOnFirstErrorClick = useCallback(() => {
  228. enableStopOnFirstError()
  229. startCompile({ stopOnFirstError: true })
  230. setAnimateCompileDropdownArrow(true)
  231. }, [enableStopOnFirstError, startCompile, setAnimateCompileDropdownArrow])
  232. return (
  233. <ErrorLogEntry title={t('timedout')}>
  234. <p>{t('project_timed_out_intro')}</p>
  235. <ul>
  236. <li>
  237. <Trans
  238. i18nKey="project_timed_out_optimize_images"
  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/Optimising_very_large_image_files" />,
  242. ]}
  243. />
  244. </li>
  245. <li>
  246. <Trans
  247. i18nKey="project_timed_out_fatal_error"
  248. components={[
  249. // eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key
  250. <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" />,
  251. ]}
  252. />
  253. {!lastCompileOptions.stopOnFirstError && (
  254. <>
  255. {' '}
  256. <Trans
  257. i18nKey="project_timed_out_enable_stop_on_first_error"
  258. components={[
  259. // eslint-disable-next-line react/jsx-key
  260. <OLButton
  261. variant="info"
  262. size="sm"
  263. bs3Props={{ bsSize: 'xsmall' }}
  264. onClick={handleEnableStopOnFirstErrorClick}
  265. />,
  266. ]}
  267. />{' '}
  268. </>
  269. )}
  270. </li>
  271. </ul>
  272. <p>
  273. <Trans
  274. i18nKey="project_timed_out_learn_more"
  275. components={[
  276. // eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key
  277. <a href="https://www.overleaf.com/learn/how-to/Why_do_I_keep_getting_the_compile_timeout_error_message%3F" />,
  278. ]}
  279. />
  280. </p>
  281. </ErrorLogEntry>
  282. )
  283. }
  284. TimedOutLogEntry.propTypes = {}