diff --git a/packages/client/src/HOCs/withFileActions.js b/packages/client/src/HOCs/withFileActions.js index a6aea017c0..105767bbaa 100644 --- a/packages/client/src/HOCs/withFileActions.js +++ b/packages/client/src/HOCs/withFileActions.js @@ -62,21 +62,14 @@ export default function withFileActions(WrappedFileItem) { }; onDropZoneUpload = (files, uploadToFolder) => { - const { t, dragging, setDragging, startUpload, uploadEmptyFolders } = + const { t, dragging, setDragging, startUpload, createFoldersTree } = this.props; dragging && setDragging(false); - const emptyFolders = files.filter((f) => f.isEmptyDirectory); - - if (emptyFolders.length > 0) { - uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => { - const onlyFiles = files.filter((f) => !f.isEmptyDirectory); - if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t); - }); - } else { - startUpload(files, uploadToFolder, t); - } + createFoldersTree(files, uploadToFolder).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }; onDrop = (items) => { @@ -371,7 +364,7 @@ export default function withFileActions(WrappedFileItem) { onSelectItem, //setNewBadgeCount, openFileAction, - uploadEmptyFolders, + createFoldersTree, } = filesActionsStore; const { setSharingPanelVisible } = dialogsStore; const { @@ -475,7 +468,7 @@ export default function withFileActions(WrappedFileItem) { dragging, setDragging, startUpload, - uploadEmptyFolders, + createFoldersTree, draggable, setTooltipPosition, setStartDrag, diff --git a/packages/client/src/components/Article/Body/Items.js b/packages/client/src/components/Article/Body/Items.js index f4b212e4fa..e06439b783 100644 --- a/packages/client/src/components/Article/Body/Items.js +++ b/packages/client/src/components/Article/Body/Items.js @@ -68,7 +68,7 @@ const Item = ({ onBadgeClick, showDragItems, startUpload, - uploadEmptyFolders, + createFoldersTree, setDragging, showBadge, labelBadge, @@ -86,18 +86,12 @@ const Item = ({ const onDropZoneUpload = React.useCallback( (files, uploadToFolder) => { dragging && setDragging(false); - const emptyFolders = files.filter((f) => f.isEmptyDirectory); - if (emptyFolders.length > 0) { - uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => { - const onlyFiles = files.filter((f) => !f.isEmptyDirectory); - if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t); - }); - } else { - startUpload(files, uploadToFolder, t); - } + createFoldersTree(files, uploadToFolder).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }, - [t, dragging, setDragging, startUpload, uploadEmptyFolders], + [t, dragging, setDragging, startUpload, createFoldersTree], ); const onDrop = React.useCallback( @@ -193,7 +187,7 @@ const Items = ({ dragging, setDragging, startUpload, - uploadEmptyFolders, + createFoldersTree, isVisitor, isCollaborator, isAdmin, @@ -326,7 +320,7 @@ const Items = ({ t={t} setDragging={setDragging} startUpload={startUpload} - uploadEmptyFolders={uploadEmptyFolders} + createFoldersTree={createFoldersTree} item={item} setBufferSelection={setBufferSelection} dragging={dragging} @@ -388,7 +382,7 @@ const Items = ({ showText, setDragging, startUpload, - uploadEmptyFolders, + createFoldersTree, trashIsEmpty, isAdmin, isVisitor, @@ -449,7 +443,7 @@ export default inject( const { id, access: folderAccess } = selectedFolderStore; const { moveDragItems, - uploadEmptyFolders, + createFoldersTree, deleteAction, emptyTrashInProgress, } = filesActionsStore; @@ -478,7 +472,7 @@ export default inject( setBufferSelection, deleteAction, startUpload, - uploadEmptyFolders, + createFoldersTree, setEmptyTrashDialogVisible, trashIsEmpty, diff --git a/packages/client/src/components/Article/MainButton/index.js b/packages/client/src/components/Article/MainButton/index.js index 6f1f4e0afb..a92377d711 100644 --- a/packages/client/src/components/Article/MainButton/index.js +++ b/packages/client/src/components/Article/MainButton/index.js @@ -70,6 +70,7 @@ import { resendInvitesAgain } from "@docspace/shared/api/people"; import { getCorrectFourValuesStyle } from "@docspace/shared/utils"; import { ArticleButtonLoader } from "@docspace/shared/skeletons/article"; import { isMobile, isTablet } from "react-device-detect"; +import getFilesFromEvent from "@docspace/shared/components/drag-and-drop/get-files-from-event"; const StyledButton = styled(Button)` font-weight: 700; @@ -180,6 +181,7 @@ const ArticleMainButtonContent = (props) => { parentRoomType, isFolder, + createFoldersTree, } = props; const navigate = useNavigate(); @@ -239,8 +241,12 @@ const ArticleMainButtonContent = (props) => { ); const onFileChange = React.useCallback( - (e) => { - startUpload(e.target.files, null, t); + async (e) => { + const files = await getFilesFromEvent(e); + + createFoldersTree(files).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }, [startUpload, t], ); @@ -249,7 +255,7 @@ const ArticleMainButtonContent = (props) => { if (isPrivacy) { encryptionUploadDialog((encryptedFile, encrypted) => { encryptedFile.encrypted = encrypted; - startUpload([encryptedFile], null, t); + startUpload([encryptedFile], null, t); // TODO: createFoldersTree }); } else { inputFilesElement.current.click(); @@ -901,6 +907,7 @@ export default inject( versionHistoryStore, userStore, currentTariffStatusStore, + filesActionsStore, }) => { const { showArticleLoader } = clientLoadingStore; const { mainButtonMobileVisible } = filesStore; @@ -945,6 +952,8 @@ export default inject( const { frameConfig, isFrame } = settingsStore; + const { createFoldersTree } = filesActionsStore; + return { isGracePeriod, setInviteUsersWarningDialogVisible, @@ -997,6 +1006,7 @@ export default inject( isFolder, selectFileFormRoomDialogVisible, setSelectFileFormRoomDialogVisible, + createFoldersTree, }; }, )( diff --git a/packages/client/src/pages/Home/Hooks/useFiles.js b/packages/client/src/pages/Home/Hooks/useFiles.js index 2f7ac09b6e..f4e4a4baae 100644 --- a/packages/client/src/pages/Home/Hooks/useFiles.js +++ b/packages/client/src/pages/Home/Hooks/useFiles.js @@ -52,7 +52,7 @@ const useFiles = ({ dragging, setDragging, disableDrag, - uploadEmptyFolders, + createFoldersTree, startUpload, fetchFiles, @@ -118,16 +118,9 @@ const useFiles = ({ if (disableDrag) return; - const emptyFolders = files.filter((f) => f.isEmptyDirectory); - - if (emptyFolders.length > 0) { - uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => { - const onlyFiles = files.filter((f) => !f.isEmptyDirectory); - if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t); - }); - } else { - startUpload(files, uploadToFolder, t); - } + createFoldersTree(files, uploadToFolder).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }; React.useEffect(() => { diff --git a/packages/client/src/pages/Home/Section/Header/index.js b/packages/client/src/pages/Home/Section/Header/index.js index 02426716ab..9dcf561add 100644 --- a/packages/client/src/pages/Home/Section/Header/index.js +++ b/packages/client/src/pages/Home/Section/Header/index.js @@ -50,6 +50,7 @@ import { getCategoryUrl, } from "SRC_DIR/helpers/utils"; import TariffBar from "SRC_DIR/components/TariffBar"; +import getFilesFromEvent from "@docspace/shared/components/drag-and-drop/get-files-from-event"; const StyledContainer = styled.div` width: 100%; @@ -225,6 +226,7 @@ const SectionHeaderContent = (props) => { getHeaderOptions, setBufferSelection, setGroupsBufferSelection, + createFoldersTree, } = props; const location = useLocation(); @@ -239,8 +241,12 @@ const SectionHeaderContent = (props) => { const isSettingsPage = location.pathname.includes("/settings"); const onFileChange = React.useCallback( - (e) => { - startUpload(e.target.files, null, t); + async (e) => { + const files = await getFilesFromEvent(e); + + createFoldersTree(files).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }, [startUpload, t], ); @@ -639,6 +645,7 @@ export default inject( moveToRoomsPage, onClickBack, moveToPublicRoom, + createFoldersTree, } = filesActionsStore; const { setIsVisible, isVisible } = infoPanelStore; @@ -802,6 +809,7 @@ export default inject( getHeaderOptions, setBufferSelection, setGroupsBufferSelection, + createFoldersTree, }; }, )( diff --git a/packages/client/src/pages/Home/index.js b/packages/client/src/pages/Home/index.js index 197ad6b00a..d9015a5320 100644 --- a/packages/client/src/pages/Home/index.js +++ b/packages/client/src/pages/Home/index.js @@ -82,7 +82,7 @@ const PureHome = (props) => { startUpload, setDragging, dragging, - uploadEmptyFolders, + createFoldersTree, disableDrag, uploaded, converted, @@ -182,7 +182,7 @@ const PureHome = (props) => { dragging, setDragging, disableDrag, - uploadEmptyFolders, + createFoldersTree, startUpload, fetchFiles, fetchRooms, @@ -543,7 +543,7 @@ export default inject( const { setUploadPanelVisible, startUpload, uploaded, converted } = uploadDataStore; - const { uploadEmptyFolders, onClickBack } = filesActionsStore; + const { createFoldersTree, onClickBack } = filesActionsStore; const selectionLength = isProgressFinished ? selection.length : null; const selectionTitle = isProgressFinished @@ -635,7 +635,7 @@ export default inject( setUploadPanelVisible, startUpload, - uploadEmptyFolders, + createFoldersTree, setToPreviewFile, setIsPreview, diff --git a/packages/client/src/store/FilesActionsStore.js b/packages/client/src/store/FilesActionsStore.js index 1349a9ec62..0cb008057d 100644 --- a/packages/client/src/store/FilesActionsStore.js +++ b/packages/client/src/store/FilesActionsStore.js @@ -229,17 +229,21 @@ class FilesActionStore { let level = { result }; try { folders.forEach((folder) => { - folder.path - .split("/") - .filter((name) => name !== "") - .reduce((r, name, i, a) => { - if (!r[name]) { - r[name] = { result: [] }; - r.result.push({ name, children: r[name].result }); - } + const folderPath = folder.path.split("/").filter((name) => name !== ""); - return r[name]; - }, level); + folderPath.reduce((r, name, i, a) => { + if (!r[name]) { + r[name] = { result: [] }; + r.result.push({ + name, + children: r[name].result, + isFile: folderPath.length - 1 === i && !folder.isEmptyDirectory, + file: folder, + }); + } + + return r[name]; + }, level); }); } catch (e) { console.error("convertToTree", e); @@ -247,52 +251,67 @@ class FilesActionStore { return result; }; - createFolderTree = async (treeList, parentFolderId) => { + createFolderTree = async (treeList, parentFolderId, filesList) => { if (!treeList || !treeList.length) return; for (let i = 0; i < treeList.length; i++) { const treeNode = treeList[i]; + const isFile = treeList[i].isFile; // console.log( // `createFolderTree parent id = ${parentFolderId} name '${treeNode.name}': `, // treeNode.children // ); + if (isFile) { + treeList[i].file.parentFolderId = parentFolderId; + filesList.push(treeList[i].file); + continue; + } + const folder = await createFolder(parentFolderId, treeNode.name); const parentId = folder.id; if (treeNode.children.length == 0) continue; - await this.createFolderTree(treeNode.children, parentId); + await this.createFolderTree(treeNode.children, parentId, filesList); } + + return treeList; }; - uploadEmptyFolders = async (emptyFolders, folderId) => { - //console.log("uploadEmptyFolders", emptyFolders, folderId); + createFoldersTree = async (files, folderId) => { + //console.log("createFoldersTree", files, folderId); - const { secondaryProgressDataStore } = this.uploadDataStore; - const { setSecondaryProgressBarData, clearSecondaryProgressData } = - secondaryProgressDataStore; + const { primaryProgressDataStore } = this.uploadDataStore; + + const { setPrimaryProgressBarData, clearPrimaryProgressData } = + primaryProgressDataStore; const operationId = uniqueid("operation_"); const toFolderId = folderId ? folderId : this.selectedFolderStore.id; - setSecondaryProgressBarData({ - icon: "file", + setPrimaryProgressBarData({ + icon: "upload", visible: true, percent: 0, label: "", alert: false, - operationId, }); - const tree = this.convertToTree(emptyFolders); - await this.createFolderTree(tree, toFolderId); + const tree = this.convertToTree(files); + + const filesList = []; + await this.createFolderTree(tree, toFolderId, filesList); this.updateCurrentFolder(null, [folderId], null, operationId); - setTimeout(() => clearSecondaryProgressData(operationId), TIMEOUT); + if (!filesList.length) { + setTimeout(() => clearPrimaryProgressData(), TIMEOUT); + } + + return filesList; }; updateFilesAfterDelete = (operationId) => { diff --git a/packages/client/src/store/HotkeyStore.js b/packages/client/src/store/HotkeyStore.js index 46ed343cdb..559ed6d98d 100644 --- a/packages/client/src/store/HotkeyStore.js +++ b/packages/client/src/store/HotkeyStore.js @@ -683,9 +683,8 @@ class HotkeyStore { }; uploadClipboardFiles = async (t, event) => { - const { uploadEmptyFolders } = this.filesActionsStore; + const { createFoldersTree } = this.filesActionsStore; const { startUpload } = this.uploadDataStore; - const currentFolderId = this.selectedFolderStore.id; if (this.filesStore.hotkeysClipboard.length) { return this.moveFilesFromClipboard(t); @@ -693,16 +692,9 @@ class HotkeyStore { const files = await getFilesFromEvent(event); - const emptyFolders = files.filter((f) => f.isEmptyDirectory); - - if (emptyFolders.length > 0) { - uploadEmptyFolders(emptyFolders, currentFolderId).then(() => { - const onlyFiles = files.filter((f) => !f.isEmptyDirectory); - if (onlyFiles.length > 0) startUpload(onlyFiles, currentFolderId, t); - }); - } else { - startUpload(files, currentFolderId, t); - } + createFoldersTree(files, uploadToFolder).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }; get countTilesInRow() { diff --git a/packages/client/src/store/UploadDataStore.js b/packages/client/src/store/UploadDataStore.js index 34f3cdb11b..711e0e6aa7 100644 --- a/packages/client/src/store/UploadDataStore.js +++ b/packages/client/src/store/UploadDataStore.js @@ -773,7 +773,8 @@ class UploadDataStore { file: file, uniqueId: uniqueid("download_row-key_"), fileId: null, - toFolderId, + // toFolderId, + toFolderId: file.parentFolderId, action: "upload", error: file.size ? null : t("Files:EmptyFile"), fileInfo: null, @@ -1372,7 +1373,7 @@ class UploadDataStore { toFolderId, fileName, fileSize, - relativePath, + "", // relativePath, file.encrypted, file.lastModifiedDate, createNewIfExist,