diff --git a/backend/controllers/file.ts b/backend/controllers/file.ts index d518645..a87a219 100644 --- a/backend/controllers/file.ts +++ b/backend/controllers/file.ts @@ -401,10 +401,12 @@ class FileController { try { const userID = req.user._id; let searchQuery = req.query.search || ""; + const trashMode = req.query.trashMode === "true"; const { fileList, folderList } = await fileService.getSuggestedList( userID, - searchQuery + searchQuery, + trashMode ); return res.send({ folderList, fileList }); diff --git a/backend/db/utils/fileUtils/index.ts b/backend/db/utils/fileUtils/index.ts index 683907c..0c2413b 100644 --- a/backend/db/utils/fileUtils/index.ts +++ b/backend/db/utils/fileUtils/index.ts @@ -133,10 +133,15 @@ class DbUtil { return user; }; - getFileSearchList = async (userID: string, searchQuery: RegExp) => { + getFileSearchList = async ( + userID: string, + searchQuery: RegExp, + trashMode: boolean + ) => { let query: any = { "metadata.owner": userID, filename: searchQuery, + "metadata.trashed": trashMode ? true : null, }; const fileList = (await conn.db diff --git a/backend/db/utils/folderUtils/index.ts b/backend/db/utils/folderUtils/index.ts index 8ae52ef..73c5674 100644 --- a/backend/db/utils/folderUtils/index.ts +++ b/backend/db/utils/folderUtils/index.ts @@ -4,8 +4,16 @@ import { ObjectId } from "mongodb"; class DbUtil { constructor() {} - getFolderSearchList = async (userID: string, searchQuery: RegExp) => { - let query: any = { owner: userID, name: searchQuery }; + getFolderSearchList = async ( + userID: string, + searchQuery: RegExp, + trashMode: boolean + ) => { + let query: any = { + owner: userID, + name: searchQuery, + trashed: trashMode ? true : null, + }; const folderList = (await Folder.find(query).limit( 10 @@ -75,7 +83,8 @@ class DbUtil { storageType: string, folderSearch: boolean, itemType: string, - s3Enabled: boolean + s3Enabled: boolean, + trashMode: boolean ) => { let query: any = { name: searchQuery, owner: userID }; @@ -105,6 +114,12 @@ class DbUtil { query = { ...query, personalFolder: null }; } + if (trashMode) { + query = { ...query, trashed: true }; + } else { + query = { ...query, trashed: null }; + } + const folderList = (await Folder.find(query).sort( sortBy )) as FolderInterface[]; diff --git a/backend/services/FileService/index.ts b/backend/services/FileService/index.ts index a515243..2030001 100644 --- a/backend/services/FileService/index.ts +++ b/backend/services/FileService/index.ts @@ -203,13 +203,22 @@ class MongoFileService { await removedTokenUser.save(); }; - getSuggestedList = async (userID: string, searchQuery: any) => { + getSuggestedList = async ( + userID: string, + searchQuery: any, + trashMode: boolean + ) => { searchQuery = new RegExp(searchQuery, "i"); - const fileList = await dbUtilsFile.getFileSearchList(userID, searchQuery); + const fileList = await dbUtilsFile.getFileSearchList( + userID, + searchQuery, + trashMode + ); const folderList = await dbUtilsFolder.getFolderSearchList( userID, - searchQuery + searchQuery, + trashMode ); if (!fileList || !folderList) diff --git a/backend/services/FolderService/index.ts b/backend/services/FolderService/index.ts index f7b851f..436a8bc 100644 --- a/backend/services/FolderService/index.ts +++ b/backend/services/FolderService/index.ts @@ -153,7 +153,8 @@ class FolderService { storageType, folderSearch, itemType, - s3Enabled + s3Enabled, + trashMode ); if (!folderList) throw new NotFoundError("Folder List Not Found Error"); diff --git a/public/assets/homea.svg b/public/assets/homea.svg index 53cf3b1..99793cd 100644 --- a/public/assets/homea.svg +++ b/public/assets/homea.svg @@ -1,10 +1,10 @@ diff --git a/src/api/filesAPI.ts b/src/api/filesAPI.ts index 86c2c0d..6259e59 100644 --- a/src/api/filesAPI.ts +++ b/src/api/filesAPI.ts @@ -84,11 +84,14 @@ export const getFileThumbnailAPI = async (thumbnailID: string) => { export const getSuggestedListAPI = async ({ queryKey, -}: QueryFunctionContext<[string, { searchText: string }]>) => { - const [_key, { searchText }] = queryKey; +}: QueryFunctionContext< + [string, { searchText: string; trashMode: boolean }] +>) => { + const [_key, { searchText, trashMode }] = queryKey; const response = await axios.get(`/file-service/suggested-list`, { params: { search: searchText, + trashMode, }, }); return response.data; diff --git a/src/components/ContextMenu/index.jsx b/src/components/ContextMenu/index.jsx index b7e4f6c..cce1d60 100644 --- a/src/components/ContextMenu/index.jsx +++ b/src/components/ContextMenu/index.jsx @@ -17,15 +17,23 @@ import { renameFolder, trashFolderAPI, } from "../../api/foldersAPI"; -import { useClickOutOfBounds } from "../../hooks/utils"; +import { useClickOutOfBounds, useUtils } from "../../hooks/utils"; import { useAppDispatch } from "../../hooks/store"; import { setMultiSelectMode } from "../../reducers/selected"; +import TrashIcon from "../../icons/TrashIcon"; +import MultiSelectIcon from "../../icons/MultiSelectIcon"; +import RenameIcon from "../../icons/RenameIcon"; +import ShareIcon from "../../icons/ShareIcon"; +import DownloadIcon from "../../icons/DownloadIcon"; +import MoveIcon from "../../icons/MoveIcon"; +import RestoreIcon from "../../icons/RestoreIcon"; const ContextMenu = (props) => { const { invalidateFilesCache } = useFilesClient(); const { invalidateFoldersCache } = useFoldersClient(); const { invalidateQuickFilesCache } = useQuickFilesClient(); const { wrapperRef } = useClickOutOfBounds(props.closeContext); + const { isTrash } = useUtils(); const dispatch = useAppDispatch(); const liClassname = "flex w-full px-[20px] py-[12px] items-center font-normal text-[#637381] justify-start no-underline transition-all duration-400 ease-in-out text- hover:bg-[#f6f5fd] hover:text-[#3c85ee] hover:font-medium"; @@ -70,7 +78,7 @@ const ContextMenu = (props) => { } }; - const deleteItem = async () => { + const trashItem = async () => { props.closeContext(); if (!props.folderMode) { const result = await Swal.fire({ @@ -105,6 +113,41 @@ const ContextMenu = (props) => { } }; + const deleteItem = async () => { + props.closeContext(); + if (!props.folderMode) { + const result = await Swal.fire({ + title: "Delete file?", + text: "You will not be able to recover this file.", + icon: "warning", + showCancelButton: true, + confirmButtonColor: "#3085d6", + cancelButtonColor: "#d33", + confirmButtonText: "Yes", + }); + + if (result.value) { + await deleteFileAPI(props.file._id); + invalidateFilesCache(); + invalidateQuickFilesCache(); + } + } else { + const result = await Swal.fire({ + title: "Delete folder?", + text: "You will not be able to recover this folder.", + icon: "warning", + showCancelButton: true, + confirmButtonColor: "#3085d6", + cancelButtonColor: "#d33", + confirmButtonText: "Yes", + }); + if (result.value) { + await deleteFolder(props.folder._id); + invalidateFoldersCache(); + } + } + }; + const openMoveItemModal = async () => { props.closeContext(); if (!props.folderMode) { @@ -169,62 +212,84 @@ const ContextMenu = (props) => {
ADD NEW
- -ADD NEW
+ +Home
+ +{multiSelectCount} selected
-{multiSelectCount} selected
+