started getting move file and folder API working
This commit is contained in:
@@ -727,11 +727,11 @@ class FileController {
|
||||
}
|
||||
|
||||
try {
|
||||
const fileID = req.body.id;
|
||||
const userID = req.user._id;
|
||||
const folderID = req.body.parentID;
|
||||
const fileID = req.body.id as string;
|
||||
const userID = req.user._id as string;
|
||||
const parentID = (req.body.parentID as string) || "/";
|
||||
|
||||
await fileService.moveFile(userID, fileID, folderID);
|
||||
await fileService.moveFile(userID, fileID, parentID);
|
||||
|
||||
res.send();
|
||||
} catch (e: unknown) {
|
||||
|
||||
@@ -177,9 +177,9 @@ class FolderController {
|
||||
try {
|
||||
const userID = req.user._id;
|
||||
const folderID = req.body.id;
|
||||
const parent = req.body.parent;
|
||||
const parentID = req.body.parentID;
|
||||
|
||||
await folderService.moveFolder(userID, folderID, parent);
|
||||
await folderService.moveFolder(userID, folderID, parentID);
|
||||
|
||||
res.send();
|
||||
} catch (e: unknown) {
|
||||
|
||||
@@ -129,7 +129,7 @@ class DbUtil {
|
||||
) => {
|
||||
const folder = (await Folder.findOneAndUpdate(
|
||||
{ _id: new ObjectId(folderID), owner: userID },
|
||||
{ $set: { parent: parent, parentList: parentList } }
|
||||
{ $set: { parent: parent, parentList: parentList }, new: true }
|
||||
)) as FolderInterface;
|
||||
|
||||
return folder;
|
||||
@@ -194,7 +194,11 @@ class DbUtil {
|
||||
owner: userID,
|
||||
};
|
||||
|
||||
const idQuery = [currentParent];
|
||||
const idQuery = [];
|
||||
|
||||
if (currentParent && currentParent !== "/") {
|
||||
idQuery.push(currentParent);
|
||||
}
|
||||
|
||||
if (folderID) {
|
||||
query.parentList = { $ne: folderID };
|
||||
@@ -217,6 +221,17 @@ class DbUtil {
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
getFolderListByIncludedParent = async (userID: string, parent: string) => {
|
||||
const folderList = await Folder.find({
|
||||
owner: userID,
|
||||
parentList: {
|
||||
$in: parent,
|
||||
},
|
||||
});
|
||||
|
||||
return folderList;
|
||||
};
|
||||
}
|
||||
|
||||
export default DbUtil;
|
||||
|
||||
@@ -4,7 +4,7 @@ import env from "../enviroment/env";
|
||||
import FileSystemService from "../services/ChunkService/FileSystemService";
|
||||
import S3Service from "../services/ChunkService/S3Service";
|
||||
import FolderController from "../controllers/folder";
|
||||
import { moveFolderValidationRules } from "../middleware/Folders/FolderMiddleware";
|
||||
import { moveFolderListValidationRules } from "../middleware/Folders/FolderMiddleware";
|
||||
|
||||
let folderController: FolderController;
|
||||
|
||||
@@ -51,7 +51,7 @@ router.get(
|
||||
router.get(
|
||||
"/folder-service/move-folder-list",
|
||||
auth,
|
||||
moveFolderValidationRules,
|
||||
moveFolderListValidationRules,
|
||||
folderController.getMoveFolderList
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { query, validationResult } from "express-validator";
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { middlewareValidationFunction } from "../Utils/MiddlewareUtils";
|
||||
|
||||
export const moveFileValidationRules = [
|
||||
query("fileID").isString().withMessage("Parent must be a string"),
|
||||
query("parentID").isString().withMessage("Parent must be a string"),
|
||||
middlewareValidationFunction,
|
||||
];
|
||||
@@ -1,18 +1,9 @@
|
||||
import { query, validationResult } from "express-validator";
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { middlewareValidationFunction } from "../Utils/MiddlewareUtils";
|
||||
|
||||
export const moveFolderValidationRules = [
|
||||
export const moveFolderListValidationRules = [
|
||||
query("parent").optional().isString().withMessage("Parent must be a string"),
|
||||
query("search").optional().isString().withMessage("Search must be a string"),
|
||||
query("folderID")
|
||||
.optional()
|
||||
.isString()
|
||||
.withMessage("FolderID must be a string"),
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(400).json({ errors: errors.array() });
|
||||
}
|
||||
next();
|
||||
},
|
||||
middlewareValidationFunction,
|
||||
];
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { NextFunction } from "express";
|
||||
import { validationResult } from "express-validator";
|
||||
import { Request, Response } from "express";
|
||||
|
||||
export const middlewareValidationFunction = (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(400).json({ errors: errors.array() });
|
||||
}
|
||||
next();
|
||||
};
|
||||
@@ -315,21 +315,29 @@ class MongoFileService {
|
||||
return file;
|
||||
};
|
||||
|
||||
moveFile = async (userID: string, fileID: string, folderID: string) => {
|
||||
moveFile = async (userID: string, fileID: string, parentID: string) => {
|
||||
const file = await dbUtilsFile.getFileInfo(fileID, userID);
|
||||
|
||||
if (!file) throw new NotFoundError("Move File Not Found Error");
|
||||
|
||||
const folder = await dbUtilsFolder.getFolderInfo(folderID, userID);
|
||||
const newParentList = [];
|
||||
|
||||
if (!folder) throw new NotFoundError("Move Folder Not Found Error");
|
||||
if (parentID !== "/") {
|
||||
const folder = await dbUtilsFolder.getFolderInfo(parentID, userID);
|
||||
|
||||
const newParentList = [...folder.parentList, folder._id];
|
||||
if (!folder) throw new NotFoundError("Move Folder Not Found Error");
|
||||
|
||||
newParentList.push(...folder.parentList, folder._id);
|
||||
} else {
|
||||
newParentList.push("/");
|
||||
}
|
||||
|
||||
console.log("new parent list", newParentList, parentID);
|
||||
|
||||
const updatedFile = await dbUtilsFile.moveFile(
|
||||
fileID,
|
||||
userID,
|
||||
folderID,
|
||||
parentID,
|
||||
newParentList.toString()
|
||||
);
|
||||
|
||||
|
||||
@@ -248,16 +248,56 @@ class FolderService {
|
||||
};
|
||||
|
||||
moveFolder = async (userID: string, folderID: string, parentID: string) => {
|
||||
console.log("parentID", parentID);
|
||||
const foldersByIncludedParent =
|
||||
await utilsFolder.getFolderListByIncludedParent(userID, folderID);
|
||||
|
||||
//const newParentList = [];
|
||||
|
||||
if (parentID !== "/") {
|
||||
const folderToMoveTo = await utilsFolder.getFolderInfo(parentID, userID);
|
||||
|
||||
if (!folderToMoveTo) {
|
||||
throw new NotFoundError("Move Folder Not Found Error");
|
||||
}
|
||||
|
||||
for (let i = 0; i < foldersByIncludedParent.length; i++) {
|
||||
const currentFolder = foldersByIncludedParent[i];
|
||||
|
||||
const currentParentIndex = currentFolder.parentList.indexOf(folderID);
|
||||
|
||||
const newParentList = [
|
||||
...folderToMoveTo.parentList,
|
||||
folderToMoveTo._id.toString(),
|
||||
...currentFolder.parentList.slice(currentParentIndex + 1),
|
||||
];
|
||||
|
||||
console.log("new parent list", newParentList);
|
||||
|
||||
await utilsFolder.moveFolder(
|
||||
folderID,
|
||||
userID,
|
||||
folderToMoveTo._id.toString(),
|
||||
newParentList
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// newParentList.push("/");
|
||||
}
|
||||
|
||||
console.log("foldersByIncludedParent", foldersByIncludedParent);
|
||||
|
||||
return;
|
||||
let parentList = ["/"];
|
||||
|
||||
if (parentID.length !== 1) {
|
||||
const parentFile = await utilsFolder.getFolderInfo(parentID, userID);
|
||||
// if (parentID.length !== 1) {
|
||||
// const parentFile = await utilsFolder.getFolderInfo(parentID, userID);
|
||||
|
||||
if (!parentFile) throw new NotFoundError("Parent Folder Info Not Found");
|
||||
// if (!parentFile) throw new NotFoundError("Parent Folder Info Not Found");
|
||||
|
||||
parentList = parentFile.parentList;
|
||||
parentList.push(parentID);
|
||||
}
|
||||
// parentList = parentFile.parentList;
|
||||
// parentList.push(parentID);
|
||||
// }
|
||||
|
||||
const folder = await utilsFolder.moveFolder(
|
||||
folderID,
|
||||
|
||||
@@ -206,6 +206,14 @@ export const removeLinkAPI = async (fileID: string) => {
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const moveFileAPI = async (fileID: string, parentID: string) => {
|
||||
const response = await axios.patch(`/file-service/move`, {
|
||||
id: fileID,
|
||||
parentID,
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// DELETE
|
||||
|
||||
export const deleteFileAPI = async (fileID: string) => {
|
||||
|
||||
@@ -90,6 +90,14 @@ export const restoreFolderAPI = async (folderID: string) => {
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const moveFolderAPI = async (folderID: string, parentID: string) => {
|
||||
const response = await axios.patch(`/folder-service/move`, {
|
||||
id: folderID,
|
||||
parentID,
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// DELETE
|
||||
|
||||
export const deleteFolderAPI = async (folderID: string) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useAppDispatch, useAppSelector } from "../../hooks/store";
|
||||
import { useMoveFolders } from "../../hooks/folders";
|
||||
import { useFoldersClient, useMoveFolders } from "../../hooks/folders";
|
||||
import { FolderInterface } from "../../types/folders";
|
||||
import CloseIcon from "../../icons/CloseIcon";
|
||||
import { resetMoveModal } from "../../reducers/selected";
|
||||
@@ -10,6 +10,10 @@ import HomeIconOutline from "../../icons/HomeIconOutline";
|
||||
import ArrowBackIcon from "../../icons/ArrowBackIcon";
|
||||
import classNames from "classnames";
|
||||
import FolderIcon from "../../icons/FolderIcon";
|
||||
import { toast } from "react-toastify";
|
||||
import { moveFileAPI } from "../../api/filesAPI";
|
||||
import { useFilesClient } from "../../hooks/files";
|
||||
import { moveFolderAPI } from "../../api/foldersAPI";
|
||||
|
||||
const MoverPopup = () => {
|
||||
const [search, setSearch] = useState("");
|
||||
@@ -22,9 +26,12 @@ const MoverPopup = () => {
|
||||
const multiSelectMode = useAppSelector(
|
||||
(state) => state.selected.multiSelectMode
|
||||
);
|
||||
const [isLoadingMove, setIsLoadingMove] = useState(false);
|
||||
const file = useAppSelector((state) => state.selected.moveModal.file);
|
||||
const folder = useAppSelector((state) => state.selected.moveModal.folder);
|
||||
const dispatch = useAppDispatch();
|
||||
const { invalidateFilesCache } = useFilesClient();
|
||||
const { invalidateFoldersCache } = useFoldersClient();
|
||||
const lastSelected = useRef({
|
||||
timestamp: 0,
|
||||
folderID: "",
|
||||
@@ -59,7 +66,7 @@ const MoverPopup = () => {
|
||||
setDebouncedSearch("");
|
||||
setParentList([...parentList, folder]);
|
||||
setParent(folder);
|
||||
setSelectedFolder(folder);
|
||||
setSelectedFolder(null);
|
||||
} else {
|
||||
setSelectedFolder(folder);
|
||||
}
|
||||
@@ -83,14 +90,21 @@ const MoverPopup = () => {
|
||||
};
|
||||
|
||||
const moveText = useMemo(() => {
|
||||
if (selectedFolder?._id) {
|
||||
return "Move to selected folder";
|
||||
if (selectedFolder?._id && selectedFolder?.name) {
|
||||
let reducedLengthFileName = selectedFolder.name;
|
||||
if (reducedLengthFileName.length > 10)
|
||||
reducedLengthFileName = reducedLengthFileName.substring(0, 10) + "...";
|
||||
return `Move to ${reducedLengthFileName}`;
|
||||
} else if (!parent) {
|
||||
return "Move home";
|
||||
return "Move to home";
|
||||
} else {
|
||||
return "Move here";
|
||||
const lastParent = parentList[parentList.length - 1];
|
||||
let reducedLengthFileName = lastParent.name;
|
||||
if (reducedLengthFileName.length > 10)
|
||||
reducedLengthFileName = reducedLengthFileName.substring(0, 10) + "...";
|
||||
return `Move to ${reducedLengthFileName}`;
|
||||
}
|
||||
}, [selectedFolder?._id, parent?._id]);
|
||||
}, [selectedFolder?._id, selectedFolder?.name, parent?._id]);
|
||||
|
||||
const headerText = useMemo(() => {
|
||||
if (parent) {
|
||||
@@ -108,14 +122,40 @@ const MoverPopup = () => {
|
||||
setSelectedFolder(null);
|
||||
};
|
||||
|
||||
const onMoveClick = () => {
|
||||
const onMoveClick = async () => {
|
||||
setIsLoadingMove(true);
|
||||
const moveTo = selectedFolder?._id
|
||||
? selectedFolder?._id
|
||||
: parent?._id || "/";
|
||||
if (file) {
|
||||
} else if (folder) {
|
||||
try {
|
||||
if (multiSelectMode) {
|
||||
} else if (file) {
|
||||
await toast.promise(moveFileAPI(file._id, moveTo), {
|
||||
pending: "Moving File...",
|
||||
success: "File Moved",
|
||||
error: "Error Moving File",
|
||||
});
|
||||
invalidateFilesCache();
|
||||
dispatch(resetMoveModal());
|
||||
} else if (folder) {
|
||||
await toast.promise(moveFolderAPI(folder._id, moveTo), {
|
||||
pending: "Moving Folder...",
|
||||
success: "Folder Moved",
|
||||
error: "Error Moving Folder",
|
||||
});
|
||||
invalidateFoldersCache();
|
||||
dispatch(resetMoveModal());
|
||||
}
|
||||
console.log("move to", moveTo);
|
||||
} catch (e) {
|
||||
console.log("move error", e);
|
||||
} finally {
|
||||
setIsLoadingMove(false);
|
||||
}
|
||||
console.log("move to", moveTo);
|
||||
};
|
||||
|
||||
const onTitleClick = () => {
|
||||
setSelectedFolder(parentList[parentList.length - 1]);
|
||||
};
|
||||
|
||||
const closeMoverModal = (e: any) => {
|
||||
@@ -163,7 +203,10 @@ const MoverPopup = () => {
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-lg mt-2 mb-2 max-w-[75%] text-ellipsis overflow-hidden">
|
||||
<p
|
||||
className="text-lg mt-2 mb-2 max-w-[75%] text-ellipsis overflow-hidden select-none cursor-pointer"
|
||||
onClick={onTitleClick}
|
||||
>
|
||||
{headerText}
|
||||
</p>
|
||||
</div>
|
||||
@@ -206,9 +249,13 @@ const MoverPopup = () => {
|
||||
<div className="flex justify-end mt-4">
|
||||
<button
|
||||
className={classNames(
|
||||
"bg-primary hover:bg-primary-hover text-white px-4 py-2 rounded-md"
|
||||
"bg-primary hover:bg-primary-hover text-white px-4 py-2 rounded-md",
|
||||
{
|
||||
"opacity-50": isLoadingMove,
|
||||
}
|
||||
)}
|
||||
onClick={onMoveClick}
|
||||
disabled={isLoadingMove}
|
||||
>
|
||||
{moveText}
|
||||
</button>
|
||||
|
||||
@@ -264,14 +264,14 @@ const PhotoViewerPopup: React.FC<PhotoViewerPopupProps> = memo((props) => {
|
||||
<div className="flex mr-4">
|
||||
<div onClick={onContextMenu} id="action-context-wrapper">
|
||||
<ActionsIcon
|
||||
className="pointer text-white w-[20px] h-[25px] mr-4 cursor-pointer"
|
||||
className="pointer text-white w-[20px] h-[25px] mr-4 cursor-pointer hover:text-white-hover"
|
||||
id="action-context-icon"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div onClick={closePhotoViewer} id="action-close-wrapper">
|
||||
<CloseIcon
|
||||
className="pointer text-white w-[25px] h-[25px] cursor-pointer"
|
||||
className="pointer text-white w-[25px] h-[25px] cursor-pointer hover:text-white-hover"
|
||||
id="action-close-icon"
|
||||
/>
|
||||
</div>
|
||||
@@ -280,11 +280,11 @@ const PhotoViewerPopup: React.FC<PhotoViewerPopupProps> = memo((props) => {
|
||||
<div className="flex absolute pb-[70px] desktopMode:pb-0 top-[50px] bottom-0 w-full h-full justify-between items-end desktopMode:items-center p-4">
|
||||
<CircleLeftIcon
|
||||
onClick={goToPreviousItem}
|
||||
className="pointer text-white w-[45px] h-[45px] desktopMode:w-[30px] desktopMode:h-[30px] select-none cursor-pointer"
|
||||
className="pointer text-white w-[45px] h-[45px] desktopMode:w-[30px] desktopMode:h-[30px] select-none cursor-pointer hover:text-white-hover"
|
||||
/>
|
||||
<CircleRightIcon
|
||||
onClick={goToNextItem}
|
||||
className="pointer text-white w-[45px] h-[45px] desktopMode:w-[30px] desktopMode:h-[30px] select-none cursor-pointer"
|
||||
className="pointer text-white w-[45px] h-[45px] desktopMode:w-[30px] desktopMode:h-[30px] select-none cursor-pointer hover:text-white-hover"
|
||||
/>
|
||||
</div>
|
||||
<div className="max-w-[80vw] max-h-[80vh] flex justify-center items-center">
|
||||
|
||||
Reference in New Issue
Block a user