error-message.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import { useTranslation, Trans } from 'react-i18next'
  2. import { FetchError } from '../../../../infrastructure/fetch-json'
  3. import RedirectToLogin from './redirect-to-login'
  4. import {
  5. BlockedFilenameError,
  6. DuplicateFilenameError,
  7. InvalidFilenameError,
  8. } from '../../errors'
  9. import DangerMessage from './danger-message'
  10. import getMeta from '@/utils/meta'
  11. // TODO: Update the error type when we properly type FileTreeActionableContext
  12. export default function ErrorMessage({
  13. error,
  14. }: {
  15. error: string | Record<string, any>
  16. }) {
  17. const { t } = useTranslation()
  18. const { isOverleaf, maxEntitiesPerProject } = getMeta('ol-ExposedSettings')
  19. const fileNameLimit = 150
  20. // the error is a string
  21. // TODO: translate? always? is this a key or a message?
  22. if (typeof error === 'string') {
  23. switch (error) {
  24. case 'name-exists':
  25. return <DangerMessage>{t('file_already_exists')}</DangerMessage>
  26. case 'too-many-files':
  27. return (
  28. <DangerMessage>
  29. {t('project_has_too_many_files_limit', {
  30. limit: maxEntitiesPerProject,
  31. })}
  32. </DangerMessage>
  33. )
  34. case 'remote-service-error':
  35. return <DangerMessage>{t('remote_service_error')}</DangerMessage>
  36. case 'folder_not_found':
  37. return (
  38. <DangerMessage>
  39. {t('the_target_folder_could_not_be_found')}
  40. </DangerMessage>
  41. )
  42. case 'invalid_filename':
  43. return (
  44. <DangerMessage>
  45. {t('invalid_filename', {
  46. nameLimit: fileNameLimit,
  47. })}
  48. </DangerMessage>
  49. )
  50. case 'invalid_upload_request':
  51. if (!isOverleaf) {
  52. return (
  53. <DangerMessage>{t('generic_something_went_wrong')}</DangerMessage>
  54. )
  55. }
  56. return (
  57. <DangerMessage>
  58. <Trans
  59. i18nKey="invalid_upload_request"
  60. // eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key
  61. components={[<a href="/contact" target="_blank" />]}
  62. />
  63. </DangerMessage>
  64. )
  65. case 'duplicate_file_name':
  66. return (
  67. <DangerMessage>
  68. {t('file_or_folder_name_already_exists')}
  69. </DangerMessage>
  70. )
  71. case 'rate-limit-hit':
  72. return (
  73. <DangerMessage>
  74. {t('too_many_files_uploaded_throttled_short_period')}
  75. </DangerMessage>
  76. )
  77. case 'not-logged-in':
  78. return (
  79. <DangerMessage>
  80. <RedirectToLogin />
  81. </DangerMessage>
  82. )
  83. case 'linked-project-compile-error':
  84. return (
  85. <DangerMessage>
  86. {t('generic_linked_file_compile_error')}
  87. </DangerMessage>
  88. )
  89. default:
  90. // TODO: convert error.response.data to an error key and try again?
  91. // return error
  92. return (
  93. <DangerMessage>{t('generic_something_went_wrong')}</DangerMessage>
  94. )
  95. }
  96. }
  97. // the error is an object
  98. // TODO: error.name?
  99. switch (error.constructor) {
  100. case FetchError: {
  101. const message = error.data?.message
  102. if (message) {
  103. return <DangerMessage>{message.text || message}</DangerMessage>
  104. }
  105. // TODO: translations
  106. switch (error.response?.status) {
  107. case 400:
  108. return <DangerMessage>{t('invalid_request')}</DangerMessage>
  109. case 403:
  110. return <DangerMessage>{t('session_error')}</DangerMessage>
  111. case 429:
  112. return <DangerMessage>{t('too_many_attempts')}</DangerMessage>
  113. default:
  114. return (
  115. <DangerMessage>{t('something_went_wrong_server')}</DangerMessage>
  116. )
  117. }
  118. }
  119. // these are handled by the filename input component
  120. case DuplicateFilenameError:
  121. case InvalidFilenameError:
  122. case BlockedFilenameError:
  123. return null
  124. // a generic error message
  125. default:
  126. // return error.message
  127. return <DangerMessage>{t('generic_something_went_wrong')}</DangerMessage>
  128. }
  129. }