preview-error.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. import PropTypes from 'prop-types'
  2. import { useTranslation, Trans } from 'react-i18next'
  3. import PreviewLogsPaneEntry from './preview-logs-pane-entry'
  4. import Icon from '../../../shared/components/icon'
  5. import { useEditorContext } from '../../../shared/context/editor-context'
  6. import StartFreeTrialButton from '../../../shared/components/start-free-trial-button'
  7. function PreviewError({ name }) {
  8. const { hasPremiumCompile, isProjectOwner } = useEditorContext({
  9. isProjectOwner: PropTypes.bool,
  10. })
  11. const { t } = useTranslation()
  12. let errorTitle
  13. let errorContent
  14. if (name === 'error') {
  15. errorTitle = t('server_error')
  16. errorContent = <>{t('somthing_went_wrong_compiling')}</>
  17. } else if (name === 'renderingError') {
  18. errorTitle = t('pdf_rendering_error')
  19. errorContent = <>{t('something_went_wrong_rendering_pdf')}</>
  20. } else if (name === 'clsiMaintenance') {
  21. errorTitle = t('server_error')
  22. errorContent = <>{t('clsi_maintenance')}</>
  23. } else if (name === 'clsiUnavailable') {
  24. errorTitle = t('server_error')
  25. errorContent = <>{t('clsi_unavailable')}</>
  26. } else if (name === 'tooRecentlyCompiled') {
  27. errorTitle = t('server_error')
  28. errorContent = <>{t('too_recently_compiled')}</>
  29. } else if (name === 'compileTerminated') {
  30. errorTitle = t('terminated')
  31. errorContent = <>{t('compile_terminated_by_user')}</>
  32. } else if (name === 'rateLimited') {
  33. errorTitle = t('pdf_compile_rate_limit_hit')
  34. errorContent = <>{t('project_flagged_too_many_compiles')}</>
  35. } else if (name === 'compileInProgress') {
  36. errorTitle = t('pdf_compile_in_progress_error')
  37. errorContent = <>{t('pdf_compile_try_again')}</>
  38. } else if (name === 'timedout') {
  39. errorTitle = t('timedout')
  40. errorContent = (
  41. <>
  42. {t('proj_timed_out_reason')}
  43. <div>
  44. <a
  45. href="https://www.overleaf.com/learn/how-to/Why_do_I_keep_getting_the_compile_timeout_error_message%3F"
  46. target="_blank"
  47. rel="noopener"
  48. >
  49. {t('learn_how_to_make_documents_compile_quickly')}
  50. </a>
  51. </div>
  52. </>
  53. )
  54. } else if (name === 'autoCompileDisabled') {
  55. errorTitle = t('autocompile_disabled')
  56. errorContent = <>{t('autocompile_disabled_reason')}</>
  57. } else if (name === 'projectTooLarge') {
  58. errorTitle = t('project_too_large')
  59. errorContent = <>{t('project_too_much_editable_text')}</>
  60. } else if (name === 'failure') {
  61. errorTitle = t('no_pdf_error_title')
  62. errorContent = (
  63. <>
  64. <Trans i18nKey="no_pdf_error_explanation" />
  65. <ul className="log-entry-formatted-content-list">
  66. <li>
  67. <Trans i18nKey="no_pdf_error_reason_unrecoverable_error" />
  68. </li>
  69. <li>
  70. <Trans
  71. i18nKey="no_pdf_error_reason_no_content"
  72. components={{ code: <code /> }}
  73. />
  74. </li>
  75. <li>
  76. <Trans
  77. i18nKey="no_pdf_error_reason_output_pdf_already_exists"
  78. components={{ code: <code /> }}
  79. />
  80. </li>
  81. </ul>
  82. </>
  83. )
  84. }
  85. return errorTitle ? (
  86. <>
  87. <PreviewLogsPaneEntry
  88. headerTitle={errorTitle}
  89. formattedContent={errorContent}
  90. entryAriaLabel={t('compile_error_entry_description')}
  91. level="error"
  92. />
  93. {name === 'timedout' &&
  94. window.ExposedSettings.enableSubscriptions &&
  95. !hasPremiumCompile ? (
  96. <TimeoutUpgradePrompt isProjectOwner={isProjectOwner} />
  97. ) : null}
  98. </>
  99. ) : null
  100. }
  101. function TimeoutUpgradePrompt({ isProjectOwner }) {
  102. const { t } = useTranslation()
  103. const timeoutUpgradePromptContent = (
  104. <>
  105. <p>{t('free_accounts_have_timeout_upgrade_to_increase')}</p>
  106. <p>{t('plus_upgraded_accounts_receive')}:</p>
  107. <div>
  108. <ul className="list-unstyled">
  109. <li>
  110. <Icon type="check" />
  111. &nbsp;
  112. {t('unlimited_projects')}
  113. </li>
  114. <li>
  115. <Icon type="check" />
  116. &nbsp;
  117. {t('collabs_per_proj', { collabcount: 'Multiple' })}
  118. </li>
  119. <li>
  120. <Icon type="check" />
  121. &nbsp;
  122. {t('full_doc_history')}
  123. </li>
  124. <li>
  125. <Icon type="check" />
  126. &nbsp;
  127. {t('sync_to_dropbox')}
  128. </li>
  129. <li>
  130. <Icon type="check" />
  131. &nbsp;
  132. {t('sync_to_github')}
  133. </li>
  134. <li>
  135. <Icon type="check" />
  136. &nbsp;
  137. {t('compile_larger_projects')}
  138. </li>
  139. </ul>
  140. </div>
  141. {isProjectOwner ? (
  142. <p className="text-center">
  143. <StartFreeTrialButton
  144. source="compile-timeout"
  145. buttonStyle="success"
  146. classes={{ button: 'row-spaced-small' }}
  147. />
  148. </p>
  149. ) : null}
  150. </>
  151. )
  152. return (
  153. <PreviewLogsPaneEntry
  154. headerTitle={
  155. isProjectOwner
  156. ? t('upgrade_for_longer_compiles')
  157. : t('ask_proj_owner_to_upgrade_for_longer_compiles')
  158. }
  159. formattedContent={timeoutUpgradePromptContent}
  160. entryAriaLabel={
  161. isProjectOwner
  162. ? t('upgrade_for_longer_compiles')
  163. : t('ask_proj_owner_to_upgrade_for_longer_compiles')
  164. }
  165. level="success"
  166. />
  167. )
  168. }
  169. PreviewError.propTypes = {
  170. name: PropTypes.string.isRequired,
  171. }
  172. TimeoutUpgradePrompt.propTypes = {
  173. isProjectOwner: PropTypes.bool.isRequired,
  174. }
  175. export default PreviewError