Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 54 additions & 142 deletions src/app/drive/components/NameCollisionDialog/NameCollisionContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,13 @@
import { FC, useMemo } from 'react';
import NameCollisionDialog, { OnSubmitPressed } from '.';
import { moveItemsToTrash } from 'views/Trash/services';
import { RootState } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/store/hooks';
import { storageActions } from 'app/store/slices/storage';
import storageThunks from 'app/store/slices/storage/storage.thunks';
import { fetchSortedFolderContentThunk } from 'app/store/slices/storage/storage.thunks/fetchSortedFolderContentThunk';
import { uiActions } from 'app/store/slices/ui';
import { DriveItemData } from 'app/drive/types';
import { IRoot } from 'app/store/slices/storage/types';
import workspacesSelectors from 'app/store/slices/workspaces/workspaces.selectors';
import { uploadFoldersWithTracking } from 'app/drive/services/folder.service/uploadFoldersWithTracking';
import replaceFileService from 'views/Drive/services/replaceFile.service';
import { Network, getEnvironmentConfig } from 'app/drive/services/network.service';
import { fileVersionsActions, fileVersionsSelectors } from 'app/store/slices/fileVersions';
import { isVersioningExtensionAllowed } from 'views/Drive/components/VersionHistory/utils';
import { checkFolderDuplicated } from 'app/store/slices/storage/folderUtils/checkFolderDuplicated';
import { getUniqueFolderName } from 'app/store/slices/storage/folderUtils/getUniqueFolderName';
import { getUniqueFilename } from 'app/store/slices/storage/fileUtils/getUniqueFilename';
import { checkDuplicatedFiles } from 'app/store/slices/storage/fileUtils/checkDuplicatedFiles';
import { CollisionGroup } from 'app/store/slices/storage/storage.model';
import { MoveItemPayload } from 'app/store/slices/storage/storage.thunks/moveItemsThunk';
import { fileVersionsSelectors } from 'app/store/slices/fileVersions';
import { NameCollisionContext, resolveCollision } from './nameCollision.actions';
import { findExistingItemFor, findPendingGroupIndex, getRemainingGroups } from './nameCollision.utils';

const NameCollisionContainer: FC = () => {
const dispatch = useAppDispatch();
Expand All @@ -31,149 +18,73 @@ const NameCollisionContainer: FC = () => {
const operationType = collisionDialogInfo?.operation;
const newItems = useMemo(() => collisionGroups.flatMap((g) => g.duplicatedItems), [collisionGroups]);
const existingItems = useMemo(() => collisionGroups.flatMap((g) => g.existingItems), [collisionGroups]);
const remainingItemsCount = existingItems.length;

const selectedWorkspace = useAppSelector(workspacesSelectors.getSelectedWorkspace);
const limits = useAppSelector(fileVersionsSelectors.getLimits);
const maxUploadFileSize = useAppSelector(fileVersionsSelectors.getMaxFileSizeLimit);
const isVersioningEnabled = limits?.versioning?.enabled ?? false;

const context: NameCollisionContext = { dispatch, selectedWorkspace, maxUploadFileSize, isVersioningEnabled };

const closeDialog = () => {
dispatch(uiActions.setIsNameCollisionDialogOpen({ open: false, info: undefined }));
};

const replaceAndMoveItem = async (group: CollisionGroup) => {
await moveItemsToTrash(group.existingItems);
await dispatch(
storageThunks.moveItemsThunk({
items: group.duplicatedItems as DriveItemData[],
destinationFolderId: group.destinationUuid,
}),
);
};

const keepAndMoveItem = async (group: CollisionGroup) => {
for (const item of group.duplicatedItems as DriveItemData[]) {
let itemParsed: MoveItemPayload;

if (item.isFolder) {
const { duplicatedFoldersResponse } = await checkFolderDuplicated([item], group.destinationUuid);
const finalName = await getUniqueFolderName(
item.plainName ?? item.name,
duplicatedFoldersResponse as DriveItemData[],
group.destinationUuid,
);
itemParsed = { ...item, name: finalName, plain_name: finalName, newItemName: finalName };
} else {
const { duplicatedFilesResponse } = await checkDuplicatedFiles([item], group.destinationUuid);
const finalName = await getUniqueFilename(item.name, item.type, duplicatedFilesResponse, group.destinationUuid);
itemParsed = { ...item, name: finalName, plainName: finalName, plain_name: finalName, newItemName: finalName };
}

await dispatch(
storageThunks.moveItemsThunk({
items: [itemParsed],
destinationFolderId: group.destinationUuid,
}),
const triggerSelectedOptionsOnSubmit = async ({ operationType, operation, applyToAll }: OnSubmitPressed) => {
if (applyToAll) {
closeDialog();
await Promise.all(
collisionGroups.map((group) =>
resolveCollision(
{
operationType,
operation,
items: group.duplicatedItems,
existingItems: group.existingItems,
destinationUuid: group.destinationUuid,
},
context,
),
),
);
return;
}
};

const uploadFileAndGetFileId = async (file: File, itemToReplace: DriveItemData) => {
const { bridgeUser, bridgePass, encryptionKey, bucketId } = await getEnvironmentConfig(!!selectedWorkspace);
const network = new Network(bridgeUser, bridgePass, encryptionKey);
const taskId = `replace-${itemToReplace.uuid}-${Date.now()}`;
const [uploadPromise] = network.uploadFile(
bucketId,
{ filecontent: file, filesize: file.size, progressCallback: () => {} },
{ taskId },
);
return uploadPromise;
};

const replaceFileVersion = async (file: File, itemToReplace: DriveItemData) => {
const newFileId = await uploadFileAndGetFileId(file, itemToReplace);
await replaceFileService.replaceFile(itemToReplace.uuid, { fileId: newFileId, size: file.size });
dispatch(fileVersionsActions.invalidateCache(itemToReplace.uuid));
};

const replaceAndUploadItem = async (group: CollisionGroup) => {
const itemsToUpload = group.duplicatedItems as (IRoot | File)[];
const itemsToReplace = group.existingItems;

for (let i = 0; i < itemsToUpload.length; i++) {
const itemToUpload = itemsToUpload[i];
const itemToReplace = itemsToReplace[i];

if ((itemToUpload as IRoot).fullPathEdited) {
await moveItemsToTrash([itemToReplace]);
await uploadFoldersWithTracking({
payload: [{ root: { ...(itemToUpload as IRoot) }, currentFolderId: group.destinationUuid }],
selectedWorkspace,
dispatch,
maxUploadFileSize,
});
} else {
const file = itemToUpload as File;
const canReplaceVersion = isVersioningEnabled && isVersioningExtensionAllowed(itemToReplace);
if (canReplaceVersion) {
await replaceFileVersion(file, itemToReplace);
} else {
await moveItemsToTrash([itemToReplace]);
await dispatch(
storageThunks.uploadItemsThunk({
files: [file],
parentFolderId: group.destinationUuid,
options: { disableDuplicatedNamesCheck: true },
}),
);
}
}

dispatch(fetchSortedFolderContentThunk(group.destinationUuid));
const groupIndex = findPendingGroupIndex(collisionGroups);
const hasPendingGroup = groupIndex !== -1;
if (!hasPendingGroup) {
closeDialog();
return;
}
};

const keepAndUploadItem = async (group: CollisionGroup) => {
for (const itemToUpload of group.duplicatedItems as (IRoot | File)[]) {
if ((itemToUpload as IRoot).fullPathEdited) {
await uploadFoldersWithTracking({
payload: [{ root: { ...(itemToUpload as IRoot) }, currentFolderId: group.destinationUuid }],
selectedWorkspace,
dispatch,
maxUploadFileSize,
});
} else {
await dispatch(
storageThunks.uploadItemsThunk({
files: [itemToUpload as File],
parentFolderId: group.destinationUuid,
}),
);
}
dispatch(fetchSortedFolderContentThunk(group.destinationUuid));
}
};
const group = collisionGroups[groupIndex];
const itemToUpload = group.duplicatedItems[0];
const itemToReplace = findExistingItemFor(itemToUpload, group.existingItems);

await resolveCollision(
{
operationType,
operation,
items: [itemToUpload],
existingItems: group.existingItems,
destinationUuid: group.destinationUuid,
},
context,
);

const triggerSelectedOptionsOnSubmit = async ({ operationType, operation }: OnSubmitPressed) => {
for (const group of collisionGroups) {
switch (operationType + operation) {
case 'move' + 'keep':
await keepAndMoveItem(group);
dispatch(storageActions.popItemsToDelete(group.duplicatedItems as DriveItemData[]));
break;
case 'move' + 'replace':
await replaceAndMoveItem(group);
dispatch(storageActions.popItemsToDelete(group.duplicatedItems as DriveItemData[]));
break;
case 'upload' + 'keep':
await keepAndUploadItem(group);
break;
case 'upload' + 'replace':
await replaceAndUploadItem(group);
break;
}
const remainingGroups = getRemainingGroups(collisionGroups, groupIndex, itemToReplace);
const hasRemainingGroups = remainingGroups.length > 0;
if (hasRemainingGroups) {
dispatch(
uiActions.setIsNameCollisionDialogOpen({
open: true,
info: { groups: remainingGroups, operation: operationType },
}),
);
} else {
closeDialog();
}
closeDialog();
};

if (!collisionDialogInfo) return null;
Expand All @@ -187,6 +98,7 @@ const NameCollisionContainer: FC = () => {
onSubmitButtonPressed={triggerSelectedOptionsOnSubmit}
onCloseDialog={closeDialog}
operationType={operationType as 'move' | 'upload'}
remainingItemsCount={remainingItemsCount}
/>
);
};
Expand Down
Loading
Loading