From 38f74c9bedf83e0a508be9cc704f8f89e4280063 Mon Sep 17 00:00:00 2001 From: subnub Date: Fri, 19 Jul 2024 03:32:21 -0400 Subject: [PATCH] started adding toasts --- package.json | 1 + src/api/foldersAPI.ts | 2 +- src/app.tsx | 1 + src/components/ContextMenu/index.tsx | 178 ++++++++++-------- src/components/Homepage/index.tsx | 3 + src/components/SharePopup/index.tsx | 45 +++-- .../SpinnerPage/{index.jsx => index.tsx} | 0 src/popups/file.ts | 28 +++ src/popups/folder.ts | 28 +++ 9 files changed, 188 insertions(+), 98 deletions(-) rename src/components/SpinnerPage/{index.jsx => index.tsx} (100%) diff --git a/package.json b/package.json index c3812b1..db57ad2 100755 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "react-query": "^3.39.3", "react-redux": "^9.1.2", "react-router-dom": "^6.23.1", + "react-toastify": "^10.0.5", "redux": "^5.0.1", "regenerator-runtime": "^0.13.3", "sharp": "^0.33.4", diff --git a/src/api/foldersAPI.ts b/src/api/foldersAPI.ts index 39cd120..f890623 100644 --- a/src/api/foldersAPI.ts +++ b/src/api/foldersAPI.ts @@ -72,7 +72,7 @@ export const restoreFolderAPI = async (folderID: string) => { // DELETE -export const deleteFolder = async (folderID: string) => { +export const deleteFolderAPI = async (folderID: string) => { const response = await axios.delete("/folder-service/remove", { data: { id: folderID, diff --git a/src/app.tsx b/src/app.tsx index c429428..c134e5e 100755 --- a/src/app.tsx +++ b/src/app.tsx @@ -7,6 +7,7 @@ import "./styles/styles.scss"; import "core-js/stable"; import "regenerator-runtime/runtime"; import "react-circular-progressbar/dist/styles.css"; +import "react-toastify/dist/ReactToastify.css"; import { QueryClient, QueryClientProvider } from "react-query"; // import '../node_modules/@fortawesome/fontawesome-free/css/all.css'; // import '../node_modules/@fortawesome/fontawesome-free/js/all.js'; diff --git a/src/components/ContextMenu/index.tsx b/src/components/ContextMenu/index.tsx index f73f598..7c6b62e 100644 --- a/src/components/ContextMenu/index.tsx +++ b/src/components/ContextMenu/index.tsx @@ -14,7 +14,7 @@ import { useDispatch } from "react-redux"; import { setMoverID } from "../../actions/mover"; import { setShareSelected } from "../../actions/selectedItem"; import { - deleteFolder, + deleteFolderAPI, renameFolder, restoreFolderAPI, trashFolderAPI, @@ -33,9 +33,16 @@ import ShareIcon from "../../icons/ShareIcon"; import DownloadIcon from "../../icons/DownloadIcon"; import MoveIcon from "../../icons/MoveIcon"; import RestoreIcon from "../../icons/RestoreIcon"; -import { restoreItemPopup } from "../../popups/file"; +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"; export interface ContextMenuProps { closeContext: () => void; @@ -65,75 +72,67 @@ const ContextMenu: React.FC = memo((props) => { const renameItem = async () => { props.closeContext(); if (!props.folderMode && props.file) { - const { value: filename } = await Swal.fire({ - title: "Enter A File Name", - input: "text", - inputValue: props.file.filename, - showCancelButton: true, - inputValidator: (value) => { - if (!value) { - return "Please Enter a Name"; - } - }, - }); - await renameFileAPI(props.file._id, filename); - invalidateFilesCache(); - invalidateQuickFilesCache(); - } else if (props.folderMode && props.folder) { - const { value: folderName } = await Swal.fire({ - title: "Enter A folder Name", - input: "text", - inputValue: props.folder.name, - showCancelButton: true, - inputValidator: (value) => { - if (!value) { - return "Please Enter a Name"; - } - }, - }); - - if (folderName === undefined || folderName === null) { - return; + try { + const filename = await renameFilePopup(props.file.filename); + if (!filename || filename === props.file.filename) return; + await toast.promise(renameFileAPI(props.file._id, filename), { + pending: "Renaming...", + success: "Renamed", + error: "Error Renaming", + }); + invalidateFilesCache(); + invalidateQuickFilesCache(); + } catch (e) { + console.log("Error renaming file", e); + } + } else if (props.folderMode && props.folder) { + try { + const folderName = await renameFolderPopup(props.folder.name); + if (!folderName || folderName === props.folder.name) return; + await toast.promise(renameFolder(props.folder._id, folderName), { + pending: "Renaming...", + success: "Renamed", + error: "Error Renaming", + }); + invalidateFoldersCache(); + } catch (e) { + console.log("Error renaming folder", e); } - - await renameFolder(props.folder._id, folderName); - invalidateFoldersCache(); } }; const trashItem = async () => { props.closeContext(); if (!props.folderMode && props.file) { - const result = await Swal.fire({ - title: "Move to trash?", - text: "Items in the trash will eventually be deleted.", - icon: "warning", - showCancelButton: true, - confirmButtonColor: "#3085d6", - cancelButtonColor: "#d33", - confirmButtonText: "Yes", - }); + try { + const result = await trashItemsPopup(); + if (!result) return; - if (result.value) { - await trashFileAPI(props.file._id); + await toast.promise(trashFileAPI(props.file._id), { + pending: "Trashing...", + success: "Trashed", + error: "Error Trashing", + }); invalidateFilesCache(); invalidateQuickFilesCache(); dispatch(resetSelected()); + } catch (e) { + console.log("Error trashing file", e); } } else if (props.folderMode && props.folder) { - const result = await Swal.fire({ - title: "Move to trash?", - text: "Items in the trash will eventually be deleted.", - icon: "warning", - showCancelButton: true, - confirmButtonColor: "#3085d6", - cancelButtonColor: "#d33", - confirmButtonText: "Yes", - }); - if (result.value) { - await trashFolderAPI(props.folder._id); + try { + const result = await trashItemsPopup(); + if (!result) return; + + await toast.promise(trashFolderAPI(props.folder._id), { + pending: "Trashing...", + success: "Trashed", + error: "Error Trashing", + }); invalidateFoldersCache(); dispatch(resetSelected()); + } catch (e) { + console.log("Error trashing folder", e); } } }; @@ -141,36 +140,35 @@ const ContextMenu: React.FC = memo((props) => { const deleteItem = async () => { props.closeContext(); if (!props.folderMode && props.file) { - 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", - }); + try { + const result = await deleteFilePopup(); + if (!result) return; - if (result.value) { - await deleteFileAPI(props.file._id); + await toast.promise(deleteFileAPI(props.file._id), { + pending: "Deleting...", + success: "Deleted", + error: "Error Deleting", + }); invalidateFilesCache(); invalidateQuickFilesCache(); dispatch(resetSelected()); + } catch (e) { + console.log("Error deleting file", e); } } else if (props.folderMode && props.folder) { - 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); + try { + const result = await deleteFolderPopup(); + if (!result) return; + + await toast.promise(deleteFolderAPI(props.folder._id), { + pending: "Deleting...", + success: "Deleted", + error: "Error Deleting", + }); invalidateFoldersCache(); dispatch(resetSelected()); + } catch (e) { + console.log("Error deleting folder", e); } } }; @@ -180,11 +178,27 @@ const ContextMenu: React.FC = memo((props) => { const result = await restoreItemPopup(); if (!result) return; if (!props.folderMode && props.file) { - await restoreFileAPI(props.file._id); - invalidateFilesCache(); + try { + await toast.promise(restoreFileAPI(props.file._id), { + pending: "Restoring...", + success: "Restored", + error: "Error Restoring", + }); + invalidateFilesCache(); + } catch (e) { + console.log("Error restoring file", e); + } } else if (props.folderMode && props.folder) { - await restoreFolderAPI(props.folder._id); - invalidateFoldersCache(); + try { + await toast.promise(restoreFolderAPI(props.folder._id), { + pending: "Restoring...", + success: "Restored", + error: "Error Restoring", + }); + invalidateFoldersCache(); + } catch (e) { + console.log("Error restoring folder", e); + } } }; diff --git a/src/components/Homepage/index.tsx b/src/components/Homepage/index.tsx index 7255676..c103dbc 100644 --- a/src/components/Homepage/index.tsx +++ b/src/components/Homepage/index.tsx @@ -6,6 +6,7 @@ import HomepageSpinner from "../HomepageSpinner"; import MobileContextMenuContainer from "../MobileContextMenu"; import PhotoViewer from "../PhotoViewer"; import { useAppSelector } from "../../hooks/store"; +import { ToastContainer } from "react-toastify"; const Homepage = () => { return ( @@ -19,6 +20,8 @@ const Homepage = () => { + + ); }; diff --git a/src/components/SharePopup/index.tsx b/src/components/SharePopup/index.tsx index 144dd08..509573a 100644 --- a/src/components/SharePopup/index.tsx +++ b/src/components/SharePopup/index.tsx @@ -2,7 +2,6 @@ import { memo, useEffect, useMemo, useState } from "react"; import CloseIcon from "../../icons/CloseIcon"; import { useAppDispatch, useAppSelector } from "../../hooks/store"; import { getFileColor, getFileExtension } from "../../utils/files"; -import ActionsIcon from "../../icons/ActionsIcon"; import bytes from "bytes"; import moment from "moment"; import { makePublicPopup, removeLinkPopup } from "../../popups/file"; @@ -17,7 +16,7 @@ import { setMainSelect, setShareModal, } from "../../reducers/selected"; -import SpinnerPage from "../SpinnerPage"; +import { toast } from "react-toastify"; const SharePopup = memo(() => { const file = useAppSelector((state) => state.selected.shareModal.file)!; @@ -49,7 +48,14 @@ const SharePopup = memo(() => { const result = await makePublicPopup(); if (!result) return; setUpdating(true); - const { file: updatedFile } = await makePublicAPI(file._id); + const { file: updatedFile } = await toast.promise( + makePublicAPI(file._id), + { + pending: "Making Public...", + success: "Public Link Generated", + error: "Error Making Public", + } + ); dispatch( setMainSelect({ file: updatedFile, @@ -62,8 +68,9 @@ const SharePopup = memo(() => { invalidateFilesCache(); } catch (e) { console.log("Error making file public", e); + } finally { + setUpdating(false); } - setUpdating(false); }; const makeOneTimePublic = async () => { @@ -71,7 +78,14 @@ const SharePopup = memo(() => { const result = await makePublicPopup(); if (!result) return; setUpdating(true); - const { file: updatedFile } = await makeOneTimePublicAPI(file._id); + const { file: updatedFile } = await toast.promise( + makeOneTimePublicAPI(file._id), + { + pending: "Making Public...", + success: "Public Link Generated", + error: "Error Making Public", + } + ); dispatch( setMainSelect({ file: updatedFile, @@ -84,8 +98,9 @@ const SharePopup = memo(() => { invalidateFilesCache(); } catch (e) { console.log("Error making file public", e); + } finally { + setUpdating(false); } - setUpdating(false); }; const removeLink = async () => { @@ -93,7 +108,11 @@ const SharePopup = memo(() => { const result = await removeLinkPopup(); if (!result) return; setUpdating(true); - const updatedFile = await removeLinkAPI(file._id); + const updatedFile = await toast.promise(removeLinkAPI(file._id), { + pending: "Removing Link...", + success: "Link Removed", + error: "Error Removing Link", + }); dispatch( setMainSelect({ file: updatedFile, @@ -107,12 +126,14 @@ const SharePopup = memo(() => { setShareLink(""); } catch (e) { console.log("Error removing link", e); + } finally { + setUpdating(false); } - setUpdating(false); }; const copyLink = () => { navigator.clipboard.writeText(shareLink); + toast.success("Link Copied"); }; const closeShareModal = () => { @@ -162,7 +183,7 @@ const SharePopup = memo(() => { -
+

Share file

@@ -246,12 +267,6 @@ const SharePopup = memo(() => {
)} - - {updating && ( -
- -
- )}
); diff --git a/src/components/SpinnerPage/index.jsx b/src/components/SpinnerPage/index.tsx similarity index 100% rename from src/components/SpinnerPage/index.jsx rename to src/components/SpinnerPage/index.tsx diff --git a/src/popups/file.ts b/src/popups/file.ts index 513b2a3..df23cda 100644 --- a/src/popups/file.ts +++ b/src/popups/file.ts @@ -1,5 +1,33 @@ import Swal from "sweetalert2"; +export const renameFilePopup = async (filename: string) => { + const result = await Swal.fire({ + title: "Enter A File Name", + input: "text", + inputValue: filename, + showCancelButton: true, + inputValidator: (value) => { + if (!value) { + return "Please Enter a Name"; + } + }, + }); + return result.value; +}; + +export const deleteFilePopup = async () => { + 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", + }); + return result.value; +}; + export const restoreItemPopup = async () => { const result = await Swal.fire({ title: "Restore item?", diff --git a/src/popups/folder.ts b/src/popups/folder.ts index 9943e19..3f89c84 100644 --- a/src/popups/folder.ts +++ b/src/popups/folder.ts @@ -1,5 +1,33 @@ import Swal from "sweetalert2"; +export const renameFolderPopup = async (folderName: string) => { + const result = await Swal.fire({ + title: "Enter A folder Name", + input: "text", + inputValue: folderName, + showCancelButton: true, + inputValidator: (value) => { + if (!value) { + return "Please Enter a Name"; + } + }, + }); + return result.value; +}; + +export const deleteFolderPopup = async () => { + 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", + }); + return result.value; +}; + export const showCreateFolderPopup = async (defaultName = "") => { const { value: folderName } = await Swal.fire({ title: "Enter Folder Name",