2024-02-15 04:48:48 -05:00
|
|
|
import { FileTreeEntity } from '../../../../../../types/file-tree-entity'
|
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import { useProjectContext } from '@/shared/context/project-context'
|
|
|
|
import { useCallback } from 'react'
|
|
|
|
import { syncDelete } from '@/features/file-tree/util/sync-mutation'
|
|
|
|
import { Button } from 'react-bootstrap'
|
2024-07-24 09:38:51 -04:00
|
|
|
import { TFunction } from 'i18next'
|
2024-02-15 04:48:48 -05:00
|
|
|
|
2024-07-24 09:38:51 -04:00
|
|
|
export type Conflict = {
|
|
|
|
entity: FileTreeEntity
|
|
|
|
type: 'file' | 'folder'
|
|
|
|
}
|
|
|
|
|
|
|
|
const getConflictText = (conflicts: Conflict[], t: TFunction) => {
|
|
|
|
const hasFolderConflict = conflicts.some(
|
|
|
|
conflict => conflict.type === 'folder'
|
|
|
|
)
|
|
|
|
|
|
|
|
const hasFileConflict = conflicts.some(conflict => conflict.type === 'file')
|
|
|
|
|
|
|
|
if (hasFolderConflict && hasFileConflict) {
|
|
|
|
return t('the_following_files_and_folders_already_exist_in_this_project')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hasFolderConflict) {
|
|
|
|
return t('the_following_folder_already_exists_in_this_project', {
|
|
|
|
count: conflicts.length,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return t('the_following_files_already_exist_in_this_project')
|
|
|
|
}
|
|
|
|
|
|
|
|
export function FileUploadConflicts({
|
2024-02-15 04:48:48 -05:00
|
|
|
cancel,
|
|
|
|
conflicts,
|
|
|
|
handleOverwrite,
|
|
|
|
}: {
|
|
|
|
cancel: () => void
|
2024-07-24 09:38:51 -04:00
|
|
|
conflicts: Conflict[]
|
2024-02-15 04:48:48 -05:00
|
|
|
handleOverwrite: () => void
|
|
|
|
}) {
|
|
|
|
const { t } = useTranslation()
|
|
|
|
|
2024-07-24 09:38:51 -04:00
|
|
|
// Don't allow overwriting folders with files
|
|
|
|
const hasFolderConflict = conflicts.some(
|
|
|
|
conflict => conflict.type === 'folder'
|
|
|
|
)
|
2024-02-15 04:48:48 -05:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="small modal-new-file--body-conflict">
|
|
|
|
{conflicts.length > 0 && (
|
|
|
|
<>
|
2024-07-24 09:38:51 -04:00
|
|
|
<p className="text-center mb-0">{getConflictText(conflicts, t)}</p>
|
2024-02-15 04:48:48 -05:00
|
|
|
|
|
|
|
<ul className="text-center list-unstyled row-spaced-small mt-1">
|
|
|
|
{conflicts.map((conflict, index) => (
|
|
|
|
<li key={index}>
|
2024-07-24 09:38:51 -04:00
|
|
|
<strong>{conflict.entity.name}</strong>
|
2024-02-15 04:48:48 -05:00
|
|
|
</li>
|
|
|
|
))}
|
|
|
|
</ul>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
|
2024-07-24 09:38:51 -04:00
|
|
|
{!hasFolderConflict && (
|
|
|
|
<p className="text-center row-spaced-small">
|
|
|
|
{t('do_you_want_to_overwrite_them')}
|
|
|
|
</p>
|
|
|
|
)}
|
2024-02-15 04:48:48 -05:00
|
|
|
|
|
|
|
<p className="text-center">
|
|
|
|
<Button bsStyle={null} className="btn-secondary" onClick={cancel}>
|
|
|
|
{t('cancel')}
|
|
|
|
</Button>
|
|
|
|
|
2024-07-24 09:38:51 -04:00
|
|
|
{!hasFolderConflict && (
|
|
|
|
<Button bsStyle="danger" onClick={handleOverwrite}>
|
|
|
|
{t('overwrite')}
|
|
|
|
</Button>
|
|
|
|
)}
|
2024-02-15 04:48:48 -05:00
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-07-24 09:38:51 -04:00
|
|
|
export function FolderUploadConflicts({
|
2024-02-15 04:48:48 -05:00
|
|
|
cancel,
|
|
|
|
handleOverwrite,
|
2024-07-24 09:38:51 -04:00
|
|
|
conflicts,
|
2024-02-15 04:48:48 -05:00
|
|
|
setError,
|
|
|
|
}: {
|
|
|
|
cancel: () => void
|
|
|
|
handleOverwrite: () => void
|
2024-07-24 09:38:51 -04:00
|
|
|
conflicts: Conflict[]
|
2024-02-15 04:48:48 -05:00
|
|
|
setError: (error: string) => void
|
|
|
|
}) {
|
|
|
|
const { t } = useTranslation()
|
|
|
|
const { _id: projectId } = useProjectContext()
|
|
|
|
|
2024-07-24 09:38:51 -04:00
|
|
|
// Don't allow overwriting files with a folder
|
|
|
|
const hasFileConflict = conflicts.some(conflict => conflict.type === 'file')
|
|
|
|
|
2024-02-15 04:48:48 -05:00
|
|
|
const deleteAndRetry = useCallback(async () => {
|
|
|
|
// TODO: confirm deletion?
|
|
|
|
|
|
|
|
try {
|
|
|
|
await Promise.all(
|
2024-07-24 09:38:51 -04:00
|
|
|
conflicts.map(conflict =>
|
|
|
|
syncDelete(projectId, 'folder', conflict.entity._id)
|
2024-02-15 04:48:48 -05:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
handleOverwrite()
|
|
|
|
} catch (error: any) {
|
|
|
|
setError(error.message)
|
|
|
|
}
|
2024-07-24 09:38:51 -04:00
|
|
|
}, [setError, conflicts, handleOverwrite, projectId])
|
2024-02-15 04:48:48 -05:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="small modal-new-file--body-conflict">
|
2024-07-24 09:38:51 -04:00
|
|
|
<p className="text-center mb-0">{getConflictText(conflicts, t)}</p>
|
2024-02-15 04:48:48 -05:00
|
|
|
|
|
|
|
<ul className="text-center list-unstyled row-spaced-small mt-1">
|
2024-07-24 09:38:51 -04:00
|
|
|
{conflicts.map((conflict, index) => (
|
2024-02-15 04:48:48 -05:00
|
|
|
<li key={index}>
|
2024-07-24 09:38:51 -04:00
|
|
|
<strong>{conflict.entity.name}</strong>
|
2024-02-15 04:48:48 -05:00
|
|
|
</li>
|
|
|
|
))}
|
|
|
|
</ul>
|
|
|
|
|
2024-07-24 09:38:51 -04:00
|
|
|
{!hasFileConflict && (
|
|
|
|
<p className="text-center row-spaced-small">
|
|
|
|
{t('overwriting_the_original_folder')}
|
|
|
|
<br />
|
|
|
|
{t('do_you_want_to_overwrite_it', {
|
|
|
|
count: conflicts.length,
|
|
|
|
})}
|
|
|
|
</p>
|
|
|
|
)}
|
2024-02-15 04:48:48 -05:00
|
|
|
|
|
|
|
<p className="text-center">
|
|
|
|
<Button bsStyle={null} className="btn-secondary" onClick={cancel}>
|
|
|
|
{t('cancel')}
|
|
|
|
</Button>
|
|
|
|
|
2024-07-24 09:38:51 -04:00
|
|
|
{!hasFileConflict && (
|
|
|
|
<Button bsStyle="danger" onClick={deleteAndRetry}>
|
|
|
|
{t('overwrite')}
|
|
|
|
</Button>
|
|
|
|
)}
|
2024-02-15 04:48:48 -05:00
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|