file-tree-upload-conflicts.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import { FileTreeEntity } from '../../../../../../types/file-tree-entity'
  2. import { useTranslation } from 'react-i18next'
  3. import { useProjectContext } from '@/shared/context/project-context'
  4. import { useCallback } from 'react'
  5. import { syncDelete } from '@/features/file-tree/util/sync-mutation'
  6. import { Button } from 'react-bootstrap'
  7. export function UploadConflicts({
  8. cancel,
  9. conflicts,
  10. folderConflicts,
  11. handleOverwrite,
  12. setError,
  13. }: {
  14. cancel: () => void
  15. conflicts: FileTreeEntity[]
  16. folderConflicts: FileTreeEntity[]
  17. handleOverwrite: () => void
  18. setError: (error: string) => void
  19. }) {
  20. const { t } = useTranslation()
  21. // ensure that no uploads happen while there are folder conflicts
  22. if (folderConflicts.length > 0) {
  23. return (
  24. <FolderUploadConflicts
  25. cancel={cancel}
  26. folderConflicts={folderConflicts}
  27. handleOverwrite={handleOverwrite}
  28. setError={setError}
  29. />
  30. )
  31. }
  32. return (
  33. <div className="small modal-new-file--body-conflict">
  34. {conflicts.length > 0 && (
  35. <>
  36. <p className="text-center mb-0">
  37. {t('the_following_files_already_exist_in_this_project')}
  38. </p>
  39. <ul className="text-center list-unstyled row-spaced-small mt-1">
  40. {conflicts.map((conflict, index) => (
  41. <li key={index}>
  42. <strong>{conflict.name}</strong>
  43. </li>
  44. ))}
  45. </ul>
  46. </>
  47. )}
  48. <p className="text-center row-spaced-small">
  49. {t('do_you_want_to_overwrite_them')}
  50. </p>
  51. <p className="text-center">
  52. <Button bsStyle={null} className="btn-secondary" onClick={cancel}>
  53. {t('cancel')}
  54. </Button>
  55. &nbsp;
  56. <Button bsStyle="danger" onClick={handleOverwrite}>
  57. {t('overwrite')}
  58. </Button>
  59. </p>
  60. </div>
  61. )
  62. }
  63. function FolderUploadConflicts({
  64. cancel,
  65. handleOverwrite,
  66. folderConflicts,
  67. setError,
  68. }: {
  69. cancel: () => void
  70. handleOverwrite: () => void
  71. folderConflicts: FileTreeEntity[]
  72. setError: (error: string) => void
  73. }) {
  74. const { t } = useTranslation()
  75. const { _id: projectId } = useProjectContext()
  76. const deleteAndRetry = useCallback(async () => {
  77. // TODO: confirm deletion?
  78. try {
  79. await Promise.all(
  80. folderConflicts.map(
  81. entity => syncDelete(projectId, 'folder', entity._id) // TODO: might be a file!
  82. )
  83. )
  84. handleOverwrite()
  85. } catch (error: any) {
  86. setError(error.message)
  87. }
  88. }, [setError, folderConflicts, handleOverwrite, projectId])
  89. return (
  90. <div className="small modal-new-file--body-conflict">
  91. <p className="text-center mb-0">
  92. {t('the_following_folder_already_exists_in_this_project', {
  93. count: folderConflicts.length,
  94. })}
  95. </p>
  96. <ul className="text-center list-unstyled row-spaced-small mt-1">
  97. {folderConflicts.map((entity, index) => (
  98. <li key={index}>
  99. <strong>{entity.name}</strong>
  100. </li>
  101. ))}
  102. </ul>
  103. <p className="text-center row-spaced-small">
  104. {t('overwriting_the_original_folder')}
  105. <br />
  106. {t('do_you_want_to_overwrite_it', {
  107. count: folderConflicts.length,
  108. })}
  109. </p>
  110. <p className="text-center">
  111. <Button bsStyle={null} className="btn-secondary" onClick={cancel}>
  112. {t('cancel')}
  113. </Button>
  114. &nbsp;
  115. <Button bsStyle="danger" onClick={deleteAndRetry}>
  116. {t('overwrite')}
  117. </Button>
  118. </p>
  119. </div>
  120. )
  121. }