preview-error.js 4.9 KB

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