From 1b44ce8dbf6345c37c4054949c7bfeebbec61d62 Mon Sep 17 00:00:00 2001 From: subnub Date: Thu, 20 Feb 2025 16:47:53 -0500 Subject: [PATCH] lots of UI improvements --- .../middleware/folders/folder-middleware.ts | 1 + .../AddNewDropdown/AddNewDropdown.tsx | 11 +- src/components/ContextMenu/ContextMenu.tsx | 311 ++++-------------- src/components/Dataform/Dataform.tsx | 4 +- src/components/FileItem/FileItem.tsx | 29 +- src/components/FolderItem/FolderItem.tsx | 24 +- src/components/LeftSection/LeftSection.tsx | 8 +- src/components/MediaItem/MediaItem.tsx | 2 +- src/components/Medias/Medias.tsx | 2 +- src/components/QuickAccess/QuickAccess.tsx | 4 +- .../QuickAccessItem/QuickAccessItem.tsx | 28 +- src/components/RightSection/RightSection.tsx | 222 +++++++++---- src/hooks/actions.ts | 267 +++++++++++++++ src/icons/ClockIcon.tsx | 17 + src/types/file.ts | 1 + src/types/folders.ts | 1 + 16 files changed, 575 insertions(+), 357 deletions(-) create mode 100644 src/hooks/actions.ts create mode 100644 src/icons/ClockIcon.tsx diff --git a/backend/middleware/folders/folder-middleware.ts b/backend/middleware/folders/folder-middleware.ts index 1281a39..5d4707a 100644 --- a/backend/middleware/folders/folder-middleware.ts +++ b/backend/middleware/folders/folder-middleware.ts @@ -8,6 +8,7 @@ export const moveFolderListValidationRules = [ query("parent").optional().isString().withMessage("Parent must be a string"), query("search").optional().isString().withMessage("Search must be a string"), query("folderIDs") + .optional() .isArray() .isLength({ min: 1 }) .withMessage("FolderIDs must be an array of strings"), diff --git a/src/components/AddNewDropdown/AddNewDropdown.tsx b/src/components/AddNewDropdown/AddNewDropdown.tsx index df23cb7..a9aa629 100644 --- a/src/components/AddNewDropdown/AddNewDropdown.tsx +++ b/src/components/AddNewDropdown/AddNewDropdown.tsx @@ -98,7 +98,10 @@ const AddNewDropdown: React.FC = (props) => { }, []); return ( -
+
= (props) => { className="flex items-center justify-start px-5 py-3 no-underline overflow-hidden text-sm bg-white hover:bg-white-hover" onClick={triggerFileUpload} > - +

Upload Files

@@ -131,7 +134,7 @@ const AddNewDropdown: React.FC = (props) => { className="flex items-center justify-start px-5 py-3 no-underline overflow-hidden text-sm bg-white hover:bg-white-hover" onClick={createFolder} > - +

Create Folder

@@ -141,7 +144,7 @@ const AddNewDropdown: React.FC = (props) => { className="flex items-center justify-start px-5 py-3 no-underline overflow-hidden text-sm bg-white hover:bg-white-hover" onClick={triggerFolderUpload} > - +

Upload Folder

diff --git a/src/components/ContextMenu/ContextMenu.tsx b/src/components/ContextMenu/ContextMenu.tsx index 03d14bc..dcd8296 100644 --- a/src/components/ContextMenu/ContextMenu.tsx +++ b/src/components/ContextMenu/ContextMenu.tsx @@ -1,27 +1,5 @@ import React, { memo, useEffect, useState } from "react"; -import { - deleteFileAPI, - renameFileAPI, - downloadFileAPI, - trashFileAPI, - restoreFileAPI, -} from "../../api/filesAPI"; -import { useFiles, useQuickFiles } from "../../hooks/files"; -import { - deleteFolderAPI, - downloadZIPAPI, - renameFolder, - restoreFolderAPI, - trashFolderAPI, -} from "../../api/foldersAPI"; import { useClickOutOfBounds, useUtils } from "../../hooks/utils"; -import { useAppDispatch } from "../../hooks/store"; -import { - resetSelected, - setMoveModal, - setMultiSelectMode, - setShareModal, -} from "../../reducers/selected"; import TrashIcon from "../../icons/TrashIcon"; import MultiSelectIcon from "../../icons/MultiSelectIcon"; import RenameIcon from "../../icons/RenameIcon"; @@ -29,18 +7,10 @@ import ShareIcon from "../../icons/ShareIcon"; import DownloadIcon from "../../icons/DownloadIcon"; import MoveIcon from "../../icons/MoveIcon"; import RestoreIcon from "../../icons/RestoreIcon"; -import { - deleteFilePopup, - renameFilePopup, - restoreItemPopup, - trashItemsPopup, -} from "../../popups/file"; import { FileInterface } from "../../types/file"; -import { FolderInterface } from "../../types/folders"; -import { toast } from "react-toastify"; -import { deleteFolderPopup, renameFolderPopup } from "../../popups/folder"; -import { useFolder, useFolders } from "../../hooks/folders"; import { useNavigate } from "react-router-dom"; +import { useActions } from "../../hooks/actions"; +import { FolderInterface } from "../../types/folders"; export interface ContextMenuProps { closeContext: () => void; @@ -63,10 +33,6 @@ const ContextMenu: React.FC = memo((props) => { Y: 0, set: false, }); - const { refetch: refetchFiles } = useFiles(false); - const { refetch: refetchFolders } = useFolders(false); - const { refetch: refetchFolder } = useFolder(false); - const { refetch: refetchQuickFiles } = useQuickFiles(false); const { closeContext, contextSelected, @@ -79,8 +45,17 @@ const ContextMenu: React.FC = memo((props) => { } = props; const { wrapperRef } = useClickOutOfBounds(closeContext); const { isTrash, isMedia } = useUtils(); - const dispatch = useAppDispatch(); const navigate = useNavigate(); + const { + renameItem, + trashItem, + deleteItem, + restoreItem, + openMoveItemModal, + openShareItemModal, + downloadItem, + selectItemMultiSelect, + } = useActions({ quickItemMode }); useEffect(() => { if (!wrapperRef.current) return; @@ -108,212 +83,54 @@ const ContextMenu: React.FC = memo((props) => { }); }, [wrapperRef, contextSelected.X, contextSelected.Y]); - const renameItem = async () => { + const onAction = async ( + action: + | "rename" + | "trash" + | "delete" + | "restore" + | "move" + | "share" + | "download" + | "multi-select" + ) => { closeContext(); - if (!folderMode && file) { - try { - const filename = await renameFilePopup(file.filename); - if (!filename || filename === file.filename) return; - await toast.promise(renameFileAPI(file._id, filename), { - pending: "Renaming...", - success: "Renamed", - error: "Error Renaming", - }); - reloadItems(); - } catch (e) { - console.log("Error renaming file", e); - } - } else if (folderMode && folder) { - try { - const folderName = await renameFolderPopup(folder.name); - if (!folderName || folderName === folder.name) return; - await toast.promise(renameFolder(folder._id, folderName), { - pending: "Renaming...", - success: "Renamed", - error: "Error Renaming", - }); - reloadItems(); - } catch (e) { - console.log("Error renaming folder", e); - } + switch (action) { + case "rename": + await renameItem(file, folder); + break; + case "trash": + await trashItem(file, folder); + break; + case "delete": + await deleteItem(file, folder); + break; + case "restore": + await restoreItem(file, folder); + break; + case "move": + await openMoveItemModal(file, folder); + break; + case "share": + openShareItemModal(file); + break; + case "download": + downloadItem(file, folder); + break; + case "multi-select": + selectItemMultiSelect(file, folder); } - }; - const trashItem = async () => { - closeContext(); - if (!folderMode && file) { - try { - const result = await trashItemsPopup(); - if (!result) return; - - await toast.promise(trashFileAPI(file._id), { - pending: "Trashing...", - success: "Trashed", - error: "Error Trashing", - }); - reloadItems(); - } catch (e) { - console.log("Error trashing file", e); + if ( + folder && + parentBarMode && + ["trash", "delete", "restore"].includes(action) + ) { + if (folder.parent === "/") { + navigate("/trash"); + } else { + navigate(`/folder-trash/${folder.parent}`); } - } else if (folderMode && folder) { - try { - const result = await trashItemsPopup(); - if (!result) return; - - await toast.promise(trashFolderAPI(folder._id), { - pending: "Trashing...", - success: "Trashed", - error: "Error Trashing", - }); - reloadItems(); - - if (parentBarMode) { - if (folder.parent === "/") { - navigate("/home"); - } else { - navigate(`/folder/${folder.parent}`); - } - } - } catch (e) { - console.log("Error trashing folder", e); - } - } - }; - - const deleteItem = async () => { - closeContext(); - if (!folderMode && file) { - try { - const result = await deleteFilePopup(); - if (!result) return; - - await toast.promise(deleteFileAPI(file._id), { - pending: "Deleting...", - success: "Deleted", - error: "Error Deleting", - }); - reloadItems(); - } catch (e) { - console.log("Error deleting file", e); - } - } else if (folderMode && folder) { - try { - const result = await deleteFolderPopup(); - if (!result) return; - - await toast.promise(deleteFolderAPI(folder._id), { - pending: "Deleting...", - success: "Deleted", - error: "Error Deleting", - }); - reloadItems(); - - if (parentBarMode) { - if (folder.parent === "/") { - navigate("/trash"); - } else { - navigate(`/folder-trash/${folder.parent}`); - } - } - } catch (e) { - console.log("Error deleting folder", e); - } - } - }; - - const restoreItem = async () => { - closeContext(); - const result = await restoreItemPopup(); - if (!result) return; - if (!folderMode && file) { - try { - await toast.promise(restoreFileAPI(file._id), { - pending: "Restoring...", - success: "Restored", - error: "Error Restoring", - }); - reloadItems(); - } catch (e) { - console.log("Error restoring file", e); - } - } else if (folderMode && folder) { - try { - await toast.promise(restoreFolderAPI(folder._id), { - pending: "Restoring...", - success: "Restored", - error: "Error Restoring", - }); - reloadItems(); - - if (parentBarMode) { - if (folder.parent === "/") { - navigate("/trash"); - } else { - navigate(`/folder-trash/${folder.parent}`); - } - } - } catch (e) { - console.log("Error restoring folder", e); - } - } - }; - - const reloadItems = () => { - refetchFiles(); - refetchQuickFiles(); - refetchFolders(); - refetchFolder(); - dispatch(resetSelected()); - }; - - const openMoveItemModal = async () => { - closeContext(); - if (!folderMode && file) { - // dispatch(setMoverID(file._id, file.metadata.parent, true)); - dispatch(setMoveModal({ type: "file", file, folder: null })); - } else if (folderMode && folder) { - // dispatch(setMoverID(folder._id, folder.parent, false)); - // } - dispatch(setMoveModal({ type: "folder", file: null, folder })); - } - }; - - const openShareItemModal = () => { - closeContext(); - dispatch(setShareModal(file!)); - }; - - const downloadItem = () => { - closeContext(); - if (file) downloadFileAPI(file._id); - if (folder) downloadZIPAPI([folder._id], []); - }; - - const selectItemMultiSelect = () => { - closeContext(); - - if (folderMode && folder) { - dispatch( - setMultiSelectMode([ - { - type: "folder", - id: folder._id, - file: null, - folder: folder, - }, - ]) - ); - } else if (!folderMode && file) { - dispatch( - setMultiSelectMode([ - { - type: quickItemMode ? "quick-item" : "file", - id: file._id, - file: file, - folder: null, - }, - ]) - ); } }; @@ -348,7 +165,7 @@ const ContextMenu: React.FC = memo((props) => {
{!parentBarMode && (
onAction("multi-select")} className="text-gray-primary flex flex-row p-4 hover:bg-white-hover hover:text-primary rounded-t-md" > @@ -357,7 +174,7 @@ const ContextMenu: React.FC = memo((props) => { )} {!isTrash && !isMedia && (
onAction("rename")} className="text-gray-primary flex flex-row p-4 hover:bg-white-hover hover:text-primary" > @@ -366,7 +183,7 @@ const ContextMenu: React.FC = memo((props) => { )} {!folderMode && !isTrash && (
onAction("share")} className="text-gray-primary flex flex-row p-4 hover:bg-white-hover hover:text-primary" > @@ -375,7 +192,7 @@ const ContextMenu: React.FC = memo((props) => { )} {!isTrash && (
onAction("download")} className="text-gray-primary flex flex-row p-4 hover:bg-white-hover hover:text-primary" > @@ -384,7 +201,7 @@ const ContextMenu: React.FC = memo((props) => { )} {!isTrash && !isMedia && (
onAction("move")} className="text-gray-primary flex flex-row p-4 hover:bg-white-hover hover:text-primary" > @@ -393,7 +210,7 @@ const ContextMenu: React.FC = memo((props) => { )} {!isTrash && (
onAction("trash")} className="text-gray-primary flex flex-row p-4 hover:bg-white-hover hover:text-primary rounded-b-md" > @@ -402,7 +219,7 @@ const ContextMenu: React.FC = memo((props) => { )} {isTrash && (
onAction("restore")} className="text-gray-primary flex flex-row p-4 hover:bg-white-hover hover:text-primary" > @@ -411,7 +228,7 @@ const ContextMenu: React.FC = memo((props) => { )} {isTrash && (
onAction("delete")} className="text-gray-primary flex flex-row p-4 hover:bg-white-hover hover:text-red-500 rounded-b-md" > diff --git a/src/components/Dataform/Dataform.tsx b/src/components/Dataform/Dataform.tsx index bf5b827..dec6344 100644 --- a/src/components/Dataform/Dataform.tsx +++ b/src/components/Dataform/Dataform.tsx @@ -118,8 +118,8 @@ const DataForm = memo( {isTrash && (
diff --git a/src/components/FileItem/FileItem.tsx b/src/components/FileItem/FileItem.tsx index 4bb4b06..2e94038 100644 --- a/src/components/FileItem/FileItem.tsx +++ b/src/components/FileItem/FileItem.tsx @@ -13,6 +13,8 @@ import ActionsIcon from "../../icons/ActionsIcon"; import { FileInterface } from "../../types/file"; import getBackendURL from "../../utils/getBackendURL"; import dayjs from "dayjs"; +import CalendarIcon from "../../icons/CalendarIcon"; +import ClockIcon from "../../icons/ClockIcon"; interface FileItemProps { file: FileInterface; @@ -168,7 +170,7 @@ const FileItem: React.FC = memo((props) => { return (
= memo((props) => { >

= memo((props) => { > {formattedFilename}

- +
+ +

+ {formattedCreatedDate} +

+
); diff --git a/src/components/FolderItem/FolderItem.tsx b/src/components/FolderItem/FolderItem.tsx index c806636..ce9cc15 100644 --- a/src/components/FolderItem/FolderItem.tsx +++ b/src/components/FolderItem/FolderItem.tsx @@ -12,6 +12,7 @@ import { import { useUtils } from "../../hooks/utils"; import { FolderInterface } from "../../types/folders"; import dayjs from "dayjs"; +import ClockIcon from "../../icons/ClockIcon"; interface FolderItemProps { folder: FolderInterface; @@ -163,16 +164,19 @@ const FolderItem: React.FC = memo((props) => { > {folder.name}

- +
+ +

+ {dayjs(folder.createdAt).format("MM/DD/YY hh:mma")} +

+
); diff --git a/src/components/LeftSection/LeftSection.tsx b/src/components/LeftSection/LeftSection.tsx index 5176513..808cc87 100644 --- a/src/components/LeftSection/LeftSection.tsx +++ b/src/components/LeftSection/LeftSection.tsx @@ -111,7 +111,7 @@ const LeftSection = ({ } )} > -
+ diff --git a/src/components/MediaItem/MediaItem.tsx b/src/components/MediaItem/MediaItem.tsx index 972646e..8342ebf 100644 --- a/src/components/MediaItem/MediaItem.tsx +++ b/src/components/MediaItem/MediaItem.tsx @@ -86,7 +86,7 @@ const MediaItem: React.FC = memo(({ file }) => { return (
diff --git a/src/components/QuickAccess/QuickAccess.tsx b/src/components/QuickAccess/QuickAccess.tsx index 6339957..bface97 100644 --- a/src/components/QuickAccess/QuickAccess.tsx +++ b/src/components/QuickAccess/QuickAccess.tsx @@ -35,8 +35,8 @@ const QuickAccess = memo(() => { ? "justify-normal" : "justify-center xs:justify-normal", { - "max-h-36 sm:max-h-40": !quickAccessExpanded, - "max-h-[720px] sm:max-h-[665px] quickAccessOne:max-h-[1000px] quickAccessTwo:max-h-[660px] quickAccessThree:max-h-[490px]": + "max-h-40": !quickAccessExpanded, + "max-h-[655px] quickAccessOne:max-h-[990px] quickAccessTwo:max-h-[660px] quickAccessThree:max-h-[490px]": quickAccessExpanded, } )} diff --git a/src/components/QuickAccessItem/QuickAccessItem.tsx b/src/components/QuickAccessItem/QuickAccessItem.tsx index e01c91c..221f442 100644 --- a/src/components/QuickAccessItem/QuickAccessItem.tsx +++ b/src/components/QuickAccessItem/QuickAccessItem.tsx @@ -15,6 +15,7 @@ import { import PlayButtonIcon from "../../icons/PlayIcon"; import dayjs from "dayjs"; import getBackendURL from "../../utils/getBackendURL"; +import ClockIcon from "../../icons/ClockIcon"; interface QuickAccessItemProps { file: FileInterface; @@ -98,7 +99,7 @@ const QuickAccessItem = memo((props: QuickAccessItemProps) => { return (
{ >

{ > {formattedFilename}

- +
+ +

+ {formattedDate} +

+
); diff --git a/src/components/RightSection/RightSection.tsx b/src/components/RightSection/RightSection.tsx index 48334dd..33f326a 100644 --- a/src/components/RightSection/RightSection.tsx +++ b/src/components/RightSection/RightSection.tsx @@ -8,10 +8,56 @@ import { resetSelected } from "../../reducers/selected"; import CloseIcon from "../../icons/CloseIcon"; import FileDetailsIcon from "../../icons/FileDetailsIcon"; import dayjs from "dayjs"; +import DownloadIcon from "../../icons/DownloadIcon"; +import ShareIcon from "../../icons/ShareIcon"; +import TrashIcon from "../../icons/TrashIcon"; +import RenameIcon from "../../icons/RenameIcon"; +import { useActions } from "../../hooks/actions"; +import RestoreIcon from "../../icons/RestoreIcon"; const RightSection = memo(() => { const selectedItem = useAppSelector((state) => state.selected.mainSection); const dispatch = useDispatch(); + const { + renameItem, + trashItem, + deleteItem, + restoreItem, + openShareItemModal, + downloadItem, + } = useActions({ + quickItemMode: false, + }); + + const onAction = async ( + action: "rename" | "trash" | "delete" | "restore" | "download" | "share" + ) => { + const file = selectedItem.file; + const folder = selectedItem.folder; + + switch (action) { + case "rename": + await renameItem(file, folder); + break; + case "trash": + await trashItem(file, folder); + break; + case "delete": + await deleteItem(file, folder); + break; + case "restore": + await restoreItem(file, folder); + break; + case "download": + downloadItem(file, folder); + break; + case "share": + openShareItemModal(file); + } + }; + + const itemTrashed = + selectedItem?.file?.metadata.trashed || selectedItem?.folder?.trashed; const formattedName = useMemo(() => { if (!selectedItem.id) return ""; @@ -81,79 +127,131 @@ const RightSection = memo(() => { > {selectedItem.id === "" ? (
- -

+ +

Select a file or folder to view it’s details

) : ( -
-
-
-
-
-

{bannerText}

+
+
+
+
+
+
+

{bannerText}

+
+
- -
- -
-
-

+

+

{formattedName}

-
-
- - Type - - - {selectedItem.file ? fileExtension : "Folder"} - -
-
- - Size - - - {fileSize} - -
-
- - Created - - - {formattedDate} - -
-
- - Access - - - {selectedItem.file?.metadata.link ? "Public" : "Private"} - + +
+

Information

+
+
+ + Type + + + {selectedItem.file ? fileExtension : "Folder"} + +
+
+ + Size + + + {fileSize} + +
+
+ + Created + + + {formattedDate} + +
+
+ + Access + + + {selectedItem.file?.metadata.link ? "Public" : "Private"} + +
+ + {/*
+
+ {!itemTrashed && ( +
onAction("download")} + > + +
+ )} + {selectedItem.file && !itemTrashed && ( +
onAction("share")} + > + +
+ )} + {itemTrashed && ( +
onAction("restore")} + > + +
+ )} +
onAction(itemTrashed ? "delete" : "trash")} + > + +
+ {!itemTrashed && ( +
onAction("rename")} + > + +
+ )} +
*/}
)}
diff --git a/src/hooks/actions.ts b/src/hooks/actions.ts new file mode 100644 index 0000000..c566b75 --- /dev/null +++ b/src/hooks/actions.ts @@ -0,0 +1,267 @@ +import { toast } from "react-toastify"; +import { + deleteFileAPI, + downloadFileAPI, + renameFileAPI, + restoreFileAPI, + trashFileAPI, +} from "../api/filesAPI"; +import { + deleteFilePopup, + renameFilePopup, + restoreItemPopup, + trashItemsPopup, +} from "../popups/file"; +import { FileInterface } from "../types/file"; +import { FolderInterface } from "../types/folders"; +import { useFiles, useQuickFiles } from "./files"; +import { useFolder, useFolders } from "./folders"; +import { useAppDispatch } from "./store"; +import { + resetSelected, + setMoveModal, + setMultiSelectMode, + setShareModal, +} from "../reducers/selected"; +import { deleteFolderPopup, renameFolderPopup } from "../popups/folder"; +import { + deleteFolderAPI, + downloadZIPAPI, + renameFolder, + restoreFolderAPI, + trashFolderAPI, +} from "../api/foldersAPI"; + +type UseActionsProps = { + quickItemMode?: boolean; +}; + +export const useActions = ({ quickItemMode }: UseActionsProps) => { + const { refetch: refetchFiles } = useFiles(false); + const { refetch: refetchFolders } = useFolders(false); + const { refetch: refetchFolder } = useFolder(false); + const { refetch: refetchQuickFiles } = useQuickFiles(false); + + const dispatch = useAppDispatch(); + + const reloadItems = () => { + refetchFiles(); + refetchQuickFiles(); + refetchFolders(); + refetchFolder(); + dispatch(resetSelected()); + }; + + const renameItem = async ( + file?: FileInterface | null, + folder?: FolderInterface | null + ) => { + if (file) { + try { + const filename = await renameFilePopup(file.filename); + if (!filename || filename === file.filename) return; + await toast.promise(renameFileAPI(file._id, filename), { + pending: "Renaming...", + success: "Renamed", + error: "Error Renaming", + }); + reloadItems(); + } catch (e) { + console.log("Error renaming file", e); + } + } else if (folder) { + try { + const folderName = await renameFolderPopup(folder.name); + if (!folderName || folderName === folder.name) return; + await toast.promise(renameFolder(folder._id, folderName), { + pending: "Renaming...", + success: "Renamed", + error: "Error Renaming", + }); + reloadItems(); + } catch (e) { + console.log("Error renaming folder", e); + } + } + }; + + const trashItem = async ( + file?: FileInterface | null, + folder?: FolderInterface | null + ) => { + if (file) { + try { + const result = await trashItemsPopup(); + if (!result) return; + + await toast.promise(trashFileAPI(file._id), { + pending: "Trashing...", + success: "Trashed", + error: "Error Trashing", + }); + reloadItems(); + } catch (e) { + console.log("Error trashing file", e); + } + } else if (folder) { + try { + const result = await trashItemsPopup(); + if (!result) return; + + await toast.promise(trashFolderAPI(folder._id), { + pending: "Trashing...", + success: "Trashed", + error: "Error Trashing", + }); + reloadItems(); + + // if (parentBarMode) { + // if (folder.parent === "/") { + // navigate("/home"); + // } else { + // navigate(`/folder/${folder.parent}`); + // } + // } + } catch (e) { + console.log("Error trashing folder", e); + } + } + }; + + const deleteItem = async ( + file?: FileInterface | null, + folder?: FolderInterface | null + ) => { + if (file) { + try { + const result = await deleteFilePopup(); + if (!result) return; + + await toast.promise(deleteFileAPI(file._id), { + pending: "Deleting...", + success: "Deleted", + error: "Error Deleting", + }); + reloadItems(); + } catch (e) { + console.log("Error deleting file", e); + } + } else if (folder) { + try { + const result = await deleteFolderPopup(); + if (!result) return; + + await toast.promise(deleteFolderAPI(folder._id), { + pending: "Deleting...", + success: "Deleted", + error: "Error Deleting", + }); + reloadItems(); + + // if (parentBarMode) { + // if (folder.parent === "/") { + // navigate("/trash"); + // } else { + // navigate(`/folder-trash/${folder.parent}`); + // } + // } + } catch (e) { + console.log("Error deleting folder", e); + } + } + }; + + const restoreItem = async ( + file?: FileInterface | null, + folder?: FolderInterface | null + ) => { + const result = await restoreItemPopup(); + if (!result) return; + if (file) { + try { + await toast.promise(restoreFileAPI(file._id), { + pending: "Restoring...", + success: "Restored", + error: "Error Restoring", + }); + reloadItems(); + } catch (e) { + console.log("Error restoring file", e); + } + } else if (folder) { + try { + await toast.promise(restoreFolderAPI(folder._id), { + pending: "Restoring...", + success: "Restored", + error: "Error Restoring", + }); + reloadItems(); + } catch (e) { + console.log("Error restoring folder", e); + } + } + }; + + const openMoveItemModal = async ( + file?: FileInterface | null, + folder?: FolderInterface | null + ) => { + if (file) { + dispatch(setMoveModal({ type: "file", file, folder: null })); + } else if (folder) { + dispatch(setMoveModal({ type: "folder", file: null, folder })); + } + }; + + const openShareItemModal = (file?: FileInterface | null) => { + dispatch(setShareModal(file!)); + }; + + const downloadItem = ( + file?: FileInterface | null, + folder?: FolderInterface | null + ) => { + if (file) downloadFileAPI(file._id); + if (folder) downloadZIPAPI([folder._id], []); + }; + + const selectItemMultiSelect = ( + file?: FileInterface | null, + folder?: FolderInterface | null + ) => { + if (folder) { + dispatch( + setMultiSelectMode([ + { + type: "folder", + id: folder._id, + file: null, + folder: folder, + }, + ]) + ); + } else if (file) { + dispatch( + setMultiSelectMode([ + { + type: quickItemMode ? "quick-item" : "file", + id: file._id, + file: file, + folder: null, + }, + ]) + ); + } + }; + + return { + renameItem, + trashItem, + deleteItem, + restoreItem, + openMoveItemModal, + openShareItemModal, + downloadItem, + selectItemMultiSelect, + }; +}; diff --git a/src/icons/ClockIcon.tsx b/src/icons/ClockIcon.tsx new file mode 100644 index 0000000..73a2861 --- /dev/null +++ b/src/icons/ClockIcon.tsx @@ -0,0 +1,17 @@ +type ClockIconType = React.SVGAttributes; + +const ClockIcon: React.FC = (props) => { + return ( + + clock-time-eight-outline + + + ); +}; + +export default ClockIcon; diff --git a/src/types/file.ts b/src/types/file.ts index aacc84b..9fb66b6 100644 --- a/src/types/file.ts +++ b/src/types/file.ts @@ -18,6 +18,7 @@ export interface FileInterface { filePath?: string; s3ID?: string; personalFile?: boolean; + trashed?: boolean; }; } interface example { diff --git a/src/types/folders.ts b/src/types/folders.ts index 7099cb3..9cbbbed 100644 --- a/src/types/folders.ts +++ b/src/types/folders.ts @@ -7,4 +7,5 @@ export interface FolderInterface { updatedAt: Date; parentList: string[]; personalFolder?: boolean; + trashed?: boolean; }