From ac91d0df9a769ba692b377d4c78019feb73eda57 Mon Sep 17 00:00:00 2001
From: Sean Hatfield <seanhatfield5@gmail.com>
Date: Mon, 23 Sep 2024 12:19:55 -0700
Subject: [PATCH] Add select/unselect all context menu to directory component
 (#2337)

add select/unselect all context menu to directory component
---
 .../Documents/Directory/ContextMenu/index.jsx | 79 +++++++++++++++++++
 .../Documents/Directory/index.jsx             | 25 +++++-
 2 files changed, 103 insertions(+), 1 deletion(-)
 create mode 100644 frontend/src/components/Modals/ManageWorkspace/Documents/Directory/ContextMenu/index.jsx

diff --git a/frontend/src/components/Modals/ManageWorkspace/Documents/Directory/ContextMenu/index.jsx b/frontend/src/components/Modals/ManageWorkspace/Documents/Directory/ContextMenu/index.jsx
new file mode 100644
index 000000000..5515d8b46
--- /dev/null
+++ b/frontend/src/components/Modals/ManageWorkspace/Documents/Directory/ContextMenu/index.jsx
@@ -0,0 +1,79 @@
+import { useRef, useEffect } from "react";
+
+export default function ContextMenu({
+  contextMenu,
+  closeContextMenu,
+  files,
+  selectedItems,
+  setSelectedItems,
+}) {
+  const contextMenuRef = useRef(null);
+
+  useEffect(() => {
+    const handleClickOutside = (event) => {
+      if (
+        contextMenuRef.current &&
+        !contextMenuRef.current.contains(event.target)
+      ) {
+        closeContextMenu();
+      }
+    };
+
+    document.addEventListener("mousedown", handleClickOutside);
+    return () => {
+      document.removeEventListener("mousedown", handleClickOutside);
+    };
+  }, [closeContextMenu]);
+
+  const isAllSelected = () => {
+    const allItems = files.items.flatMap((folder) => [
+      folder.name,
+      ...folder.items.map((file) => file.id),
+    ]);
+    return allItems.every((item) => selectedItems[item]);
+  };
+
+  const toggleSelectAll = () => {
+    if (isAllSelected()) {
+      setSelectedItems({});
+    } else {
+      const newSelectedItems = {};
+      files.items.forEach((folder) => {
+        newSelectedItems[folder.name] = true;
+        folder.items.forEach((file) => {
+          newSelectedItems[file.id] = true;
+        });
+      });
+      setSelectedItems(newSelectedItems);
+    }
+    closeContextMenu();
+  };
+
+  if (!contextMenu.visible) return null;
+
+  return (
+    <div
+      ref={contextMenuRef}
+      style={{
+        position: "fixed",
+        top: `${contextMenu.y}px`,
+        left: `${contextMenu.x}px`,
+        zIndex: 1000,
+      }}
+      className="bg-zinc-800 border border-zinc-700 rounded-md shadow-lg"
+    >
+      <button
+        onClick={toggleSelectAll}
+        className="block w-full text-left px-4 py-2 text-sm text-white hover:bg-zinc-700"
+      >
+        {isAllSelected() ? "Unselect All" : "Select All"}
+      </button>
+      <button
+        onClick={closeContextMenu}
+        className="block w-full text-left px-4 py-2 text-sm text-white hover:bg-zinc-700"
+      >
+        Cancel
+      </button>
+    </div>
+  );
+}
diff --git a/frontend/src/components/Modals/ManageWorkspace/Documents/Directory/index.jsx b/frontend/src/components/Modals/ManageWorkspace/Documents/Directory/index.jsx
index 8ad2ed6a5..d1c5eba78 100644
--- a/frontend/src/components/Modals/ManageWorkspace/Documents/Directory/index.jsx
+++ b/frontend/src/components/Modals/ManageWorkspace/Documents/Directory/index.jsx
@@ -12,6 +12,7 @@ import { useModal } from "@/hooks/useModal";
 import NewFolderModal from "./NewFolderModal";
 import debounce from "lodash.debounce";
 import { filterFileSearchResults } from "./utils";
+import ContextMenu from "./ContextMenu";
 
 function Directory({
   files,
@@ -35,6 +36,11 @@ function Directory({
     openModal: openFolderModal,
     closeModal: closeFolderModal,
   } = useModal();
+  const [contextMenu, setContextMenu] = useState({
+    visible: false,
+    x: 0,
+    y: 0,
+  });
 
   useEffect(() => {
     setAmountSelected(Object.keys(selectedItems).length);
@@ -171,8 +177,18 @@ function Directory({
   }, 500);
 
   const filteredFiles = filterFileSearchResults(files, searchTerm);
+
+  const handleContextMenu = (event) => {
+    event.preventDefault();
+    setContextMenu({ visible: true, x: event.clientX, y: event.clientY });
+  };
+
+  const closeContextMenu = () => {
+    setContextMenu({ visible: false, x: 0, y: 0 });
+  };
+
   return (
-    <div className="px-8 pb-8">
+    <div className="px-8 pb-8" onContextMenu={handleContextMenu}>
       <div className="flex flex-col gap-y-6">
         <div className="flex items-center justify-between w-[560px] px-5 relative">
           <h3 className="text-white text-base font-bold">My Documents</h3>
@@ -298,6 +314,13 @@ function Directory({
           />
         </div>
       )}
+      <ContextMenu
+        contextMenu={contextMenu}
+        closeContextMenu={closeContextMenu}
+        files={files}
+        selectedItems={selectedItems}
+        setSelectedItems={setSelectedItems}
+      />
     </div>
   );
 }
-- 
GitLab