export-document-toasts.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import { GlobalToastGeneratorEntry } from '@/features/ide-react/components/global-toasts'
  2. import { Trans, useTranslation } from 'react-i18next'
  3. const PreparingExportToast = () => {
  4. const { t } = useTranslation()
  5. return <span>{t('preparing_for_export')}</span>
  6. }
  7. const ExportDocumentErrorToast = ({ data }: { data?: any }) => {
  8. const { t } = useTranslation()
  9. const errorMessage =
  10. typeof data?.errorMessage === 'string' ? data.errorMessage : null
  11. return (
  12. <>
  13. <p>
  14. <b>{t('we_couldnt_export_this_document')}</b>
  15. </p>
  16. <Trans
  17. i18nKey="the_document_contains_formatting_we_werent_able_to_convert_contact_support_if_you_need_help"
  18. components={[
  19. // eslint-disable-next-line react/jsx-key, jsx-a11y/anchor-has-content
  20. <a href="/contact" target="_BLANK" rel="noopener noreferrer" />,
  21. ]}
  22. />
  23. {errorMessage && (
  24. <details>
  25. <summary>{t('error_details')}</summary>
  26. <pre
  27. style={{ maxWidth: '800px', maxHeight: '300px', overflow: 'auto' }}
  28. >
  29. <code>{errorMessage}</code>
  30. </pre>
  31. </details>
  32. )}
  33. </>
  34. )
  35. }
  36. const ExportDocumentSuccessToast = ({ data }: { data?: any }) => {
  37. const type = data?.type
  38. if (type === 'docx') {
  39. return (
  40. <Trans
  41. i18nKey="docx_export_feedback_message"
  42. components={[
  43. // eslint-disable-next-line react/jsx-key, jsx-a11y/anchor-has-content
  44. <a
  45. href="https://forms.gle/Fg4BUXV2yv61hStX8"
  46. target="_BLANK"
  47. rel="noopener noreferrer"
  48. />,
  49. ]}
  50. />
  51. )
  52. } else if (type === 'markdown') {
  53. return (
  54. <Trans
  55. i18nKey="markdown_export_feedback_message"
  56. components={[
  57. // eslint-disable-next-line react/jsx-key, jsx-a11y/anchor-has-content
  58. <a
  59. href="https://forms.gle/wc43zEukeqpec9mAA"
  60. target="_BLANK"
  61. rel="noopener noreferrer"
  62. />,
  63. ]}
  64. />
  65. )
  66. } else {
  67. return (
  68. <Trans
  69. i18nKey="generic_export_feedback_message"
  70. components={[
  71. // eslint-disable-next-line react/jsx-key, jsx-a11y/anchor-has-content
  72. <a href="/contact" target="_BLANK" rel="noopener noreferrer" />,
  73. ]}
  74. />
  75. )
  76. }
  77. }
  78. const generators: GlobalToastGeneratorEntry[] = [
  79. {
  80. key: 'export-document:error',
  81. generator: (data: any) => ({
  82. content: <ExportDocumentErrorToast data={data} />,
  83. type: 'error',
  84. // Only auto-hide if we have no extra details
  85. autoHide: !data?.errorMessage,
  86. delay: 5000,
  87. isDismissible: true,
  88. }),
  89. },
  90. {
  91. key: 'export-document:preparing',
  92. generator: () => ({
  93. content: <PreparingExportToast />,
  94. type: 'info',
  95. autoHide: false,
  96. isDismissible: true,
  97. }),
  98. },
  99. {
  100. key: 'export-document:success',
  101. generator: (data: any) => ({
  102. content: <ExportDocumentSuccessToast data={data} />,
  103. type: 'success',
  104. autoHide: true,
  105. delay: 45000,
  106. isDismissible: true,
  107. }),
  108. },
  109. ]
  110. export default generators
  111. // We only ever care about the latest error toast, so use a static handle.
  112. const EXPORT_DOCUMENT_ERROR_HANDLE = 'export-document-error'
  113. export const showExportDocumentError = (errorMessage?: string) => {
  114. window.dispatchEvent(
  115. new CustomEvent('ide:show-toast', {
  116. detail: {
  117. key: 'export-document:error',
  118. handle: EXPORT_DOCUMENT_ERROR_HANDLE,
  119. errorMessage,
  120. },
  121. })
  122. )
  123. }
  124. export const hideExportDocumentError = () => {
  125. window.dispatchEvent(
  126. new CustomEvent('ide:dismiss-toast', {
  127. detail: { handle: EXPORT_DOCUMENT_ERROR_HANDLE },
  128. })
  129. )
  130. }
  131. export const showPreparingExportToast = () => {
  132. const handle = `export-document-preparing-${Date.now()}`
  133. window.dispatchEvent(
  134. new CustomEvent('ide:show-toast', {
  135. detail: { key: 'export-document:preparing', handle },
  136. })
  137. )
  138. return handle
  139. }
  140. export const hidePreparingExportToast = (handle: string) => {
  141. window.dispatchEvent(
  142. new CustomEvent('ide:dismiss-toast', {
  143. detail: { key: 'export-document:preparing', handle },
  144. })
  145. )
  146. }
  147. export const showExportDocumentSuccess = (type: 'docx' | 'markdown') => {
  148. window.dispatchEvent(
  149. new CustomEvent('ide:show-toast', {
  150. detail: { key: 'export-document:success', type },
  151. })
  152. )
  153. }