From d72f1af36193200f71f5f0e52aef3d68204cc535 Mon Sep 17 00:00:00 2001
From: Timothy Carambat <rambat1010@gmail.com>
Date: Fri, 26 Apr 2024 17:41:42 -0700
Subject: [PATCH] Improve uploader experience (#1205)

* Improve uploader expierence
- Wipe upload container (fadeout) after uploading
- debounce fetchKeys by 1s

* patch unneded exports
---
 .../UploadFile/FileUploadProgress/index.jsx   | 38 ++++++++++++--
 .../Documents/UploadFile/index.jsx            | 14 +++---
 frontend/src/index.css                        | 50 +++++++++++++++++++
 3 files changed, 91 insertions(+), 11 deletions(-)

diff --git a/frontend/src/components/Modals/MangeWorkspace/Documents/UploadFile/FileUploadProgress/index.jsx b/frontend/src/components/Modals/MangeWorkspace/Documents/UploadFile/FileUploadProgress/index.jsx
index e1f4651eb..104d45a16 100644
--- a/frontend/src/components/Modals/MangeWorkspace/Documents/UploadFile/FileUploadProgress/index.jsx
+++ b/frontend/src/components/Modals/MangeWorkspace/Documents/UploadFile/FileUploadProgress/index.jsx
@@ -7,7 +7,9 @@ import PreLoader from "../../../../../Preloader";
 
 function FileUploadProgressComponent({
   slug,
+  uuid,
   file,
+  setFiles,
   rejected = false,
   reason = null,
   onUploadSuccess,
@@ -18,6 +20,19 @@ function FileUploadProgressComponent({
   const [timerMs, setTimerMs] = useState(10);
   const [status, setStatus] = useState("pending");
   const [error, setError] = useState("");
+  const [isFadingOut, setIsFadingOut] = useState(false);
+
+  const fadeOut = (cb) => {
+    setIsFadingOut(true);
+    cb?.();
+  };
+
+  const beginFadeOut = () => {
+    setIsFadingOut(false);
+    setFiles((prev) => {
+      return prev.filter((item) => item.uid !== uuid);
+    });
+  };
 
   useEffect(() => {
     async function uploadFile() {
@@ -44,13 +59,22 @@ function FileUploadProgressComponent({
         clearInterval(timer);
         onUploadSuccess();
       }
+
+      // Begin fadeout timer to clear uploader queue.
+      setTimeout(() => {
+        fadeOut(() => setTimeout(() => beginFadeOut(), 300));
+      }, 5000);
     }
     !!file && !rejected && uploadFile();
   }, []);
 
   if (rejected) {
     return (
-      <div className="h-14 px-2 py-2 flex items-center gap-x-4 rounded-lg bg-white/5 border border-white/40">
+      <div
+        className={`${
+          isFadingOut ? "file-upload-fadeout" : "file-upload"
+        } h-14 px-2 py-2 flex items-center gap-x-4 rounded-lg bg-white/5 border border-white/40`}
+      >
         <div className="w-6 h-6 flex-shrink-0">
           <XCircle className="w-6 h-6 stroke-white bg-red-500 rounded-full p-1 w-full h-full" />
         </div>
@@ -66,7 +90,11 @@ function FileUploadProgressComponent({
 
   if (status === "failed") {
     return (
-      <div className="h-14 px-2 py-2 flex items-center gap-x-4 rounded-lg bg-white/5 border border-white/40 overflow-y-auto">
+      <div
+        className={`${
+          isFadingOut ? "file-upload-fadeout" : "file-upload"
+        } h-14 px-2 py-2 flex items-center gap-x-4 rounded-lg bg-white/5 border border-white/40 overflow-y-auto`}
+      >
         <div className="w-6 h-6 flex-shrink-0">
           <XCircle className="w-6 h-6 stroke-white bg-red-500 rounded-full p-1 w-full h-full" />
         </div>
@@ -81,7 +109,11 @@ function FileUploadProgressComponent({
   }
 
   return (
-    <div className="h-14 px-2 py-2 flex items-center gap-x-4 rounded-lg bg-white/5 border border-white/40">
+    <div
+      className={`${
+        isFadingOut ? "file-upload-fadeout" : "file-upload"
+      } h-14 px-2 py-2 flex items-center gap-x-4 rounded-lg bg-white/5 border border-white/40`}
+    >
       <div className="w-6 h-6 flex-shrink-0">
         {status !== "complete" ? (
           <div className="flex items-center justify-center">
diff --git a/frontend/src/components/Modals/MangeWorkspace/Documents/UploadFile/index.jsx b/frontend/src/components/Modals/MangeWorkspace/Documents/UploadFile/index.jsx
index e57997a83..8996829c1 100644
--- a/frontend/src/components/Modals/MangeWorkspace/Documents/UploadFile/index.jsx
+++ b/frontend/src/components/Modals/MangeWorkspace/Documents/UploadFile/index.jsx
@@ -6,6 +6,7 @@ import { useDropzone } from "react-dropzone";
 import { v4 } from "uuid";
 import FileUploadProgress from "./FileUploadProgress";
 import Workspace from "../../../../../models/workspace";
+import debounce from "lodash.debounce";
 
 export default function UploadFile({
   workspace,
@@ -39,14 +40,9 @@ export default function UploadFile({
     setFetchingUrl(false);
   };
 
-  const handleUploadSuccess = () => {
-    fetchKeys(true);
-    showToast("File uploaded successfully", "success", { clear: true });
-  };
-
-  const handleUploadError = (message) => {
-    showToast(`Error uploading file: ${message}`, "error");
-  };
+  // Don't spam fetchKeys, wait 1s between calls at least.
+  const handleUploadSuccess = debounce(() => fetchKeys(true), 1000);
+  const handleUploadError = (_msg) => null; // stubbed.
 
   const onDrop = async (acceptedFiles, rejections) => {
     const newAccepted = acceptedFiles.map((file) => {
@@ -115,6 +111,8 @@ export default function UploadFile({
               <FileUploadProgress
                 key={file.uid}
                 file={file.file}
+                uuid={file.uid}
+                setFiles={setFiles}
                 slug={workspace.slug}
                 rejected={file?.rejected}
                 reason={file?.reason}
diff --git a/frontend/src/index.css b/frontend/src/index.css
index e5066f679..35159b3f1 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -692,3 +692,53 @@ does not extend the close button beyond the viewport. */
 .text-tremor-content {
   padding-bottom: 10px;
 }
+
+.file-upload {
+  -webkit-animation: fadein 0.3s linear forwards;
+  animation: fadein 0.3s linear forwards;
+}
+
+.file-upload-fadeout {
+  -webkit-animation: fadeout 0.3s linear forwards;
+  animation: fadeout 0.3s linear forwards;
+}
+
+@-webkit-keyframes fadein {
+  0% {
+    opacity: 0;
+  }
+
+  100% {
+    opacity: 1;
+  }
+}
+
+@keyframes fadein {
+  0% {
+    opacity: 0;
+  }
+
+  100% {
+    opacity: 1;
+  }
+}
+
+@-webkit-keyframes fadeout {
+  0% {
+    opacity: 1;
+  }
+
+  100% {
+    opacity: 0;
+  }
+}
+
+@keyframes fadeout {
+  0% {
+    opacity: 1;
+  }
+
+  100% {
+    opacity: 0;
+  }
+}
-- 
GitLab