From 3eecb4de2abce9c85a9b513934dfd66c5f738db4 Mon Sep 17 00:00:00 2001 From: Nathan Panchout Date: Wed, 30 Apr 2025 14:37:49 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(front)=20improve=20drag-and-drop?= =?UTF-8?q?=20validation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhanced the drag-and-drop functionality by adding a check to prevent dropping an item into its own children, ensuring a more intuitive user experience. Updated the logic for determining if a folder has loaded children based on the number of child folders and existing children. Additionally, refined the conditions for allowing drops in the ExplorerTree component, improving overall usability and consistency in item management. --- .../features/explorer/components/ExplorerDndProvider.tsx | 5 +++++ .../src/features/explorer/components/grid/ExplorerGrid.tsx | 7 +++++-- .../src/features/explorer/components/tree/ExplorerTree.tsx | 7 +++---- .../apps/drive/src/features/explorer/hooks/useUpload.tsx | 7 ++++++- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/frontend/apps/drive/src/features/explorer/components/ExplorerDndProvider.tsx b/src/frontend/apps/drive/src/features/explorer/components/ExplorerDndProvider.tsx index 5ed57c6a..ec793c1b 100644 --- a/src/frontend/apps/drive/src/features/explorer/components/ExplorerDndProvider.tsx +++ b/src/frontend/apps/drive/src/features/explorer/components/ExplorerDndProvider.tsx @@ -237,6 +237,11 @@ export const canDrop = (activeItem: Item, overItem: Item | TreeItem) => { const activePathSegments = activePath.split("."); const overPathSegments = overPath.split("."); + // Cannot drop an item into its children + if (overPath.startsWith(activePath)) { + return false; + } + if (activePathSegments.length === 1 && overPathSegments.length === 1) { return activePathSegments[0] === overPathSegments[0]; } diff --git a/src/frontend/apps/drive/src/features/explorer/components/grid/ExplorerGrid.tsx b/src/frontend/apps/drive/src/features/explorer/components/grid/ExplorerGrid.tsx index f83edf43..ca26ceba 100644 --- a/src/frontend/apps/drive/src/features/explorer/components/grid/ExplorerGrid.tsx +++ b/src/frontend/apps/drive/src/features/explorer/components/grid/ExplorerGrid.tsx @@ -97,14 +97,17 @@ export const ExplorerGrid = (props: ExplorerProps) => { ...folder, children: children, }); - item.hasLoadedChildren = true; + item.hasLoadedChildren = + folder.numchild_folder !== undefined && + folder.numchild_folder > 0 && + children.length > 0; return item; } else { const children = itemToTreeItem({ ...folder, children: [], }); - + children.hasLoadedChildren = false; return children; } }); diff --git a/src/frontend/apps/drive/src/features/explorer/components/tree/ExplorerTree.tsx b/src/frontend/apps/drive/src/features/explorer/components/tree/ExplorerTree.tsx index 40d9a990..bc4ebd9b 100644 --- a/src/frontend/apps/drive/src/features/explorer/components/tree/ExplorerTree.tsx +++ b/src/frontend/apps/drive/src/features/explorer/components/tree/ExplorerTree.tsx @@ -21,6 +21,7 @@ import { ExplorerTreeNav } from "./nav/ExplorerTreeNav"; import { addItemsMovedToast } from "../toasts/addItemsMovedToast"; import { ExplorerTreeMoveConfirmationModal } from "./ExplorerTreeMoveConfirmationModal"; import { ExplorerSearchModal } from "../modals/search/ExplorerSearchModal"; +import { canDrop } from "../ExplorerDndProvider"; export const ExplorerTree = () => { const { t, i18n } = useTranslation(); @@ -237,15 +238,13 @@ export const ExplorerTree = () => { }} canDrop={(args) => { const parent = args.parentNode?.data.value as Item | undefined; - const canDropOnParent = parent?.abilities.children_create ?? false; const activeItem = args.dragNodes[0].data.value as Item; - const canDropActiveItem = activeItem.abilities.move; - const canDropItem = canDropOnParent && canDropActiveItem; + const canDropResult = parent ? canDrop(activeItem, parent) : true; return ( args.index === 0 && args.parentNode?.willReceiveDrop === true && - canDropItem + canDropResult ); }} renderNode={ExplorerTreeItem} diff --git a/src/frontend/apps/drive/src/features/explorer/hooks/useUpload.tsx b/src/frontend/apps/drive/src/features/explorer/hooks/useUpload.tsx index cdccffb0..5d5252b6 100644 --- a/src/frontend/apps/drive/src/features/explorer/hooks/useUpload.tsx +++ b/src/frontend/apps/drive/src/features/explorer/hooks/useUpload.tsx @@ -11,6 +11,7 @@ import { FileUploadMeta } from "../components/ExplorerInner"; import { ToasterItem } from "@/features/ui/components/toaster/Toaster"; import { addToast } from "@/features/ui/components/toaster/Toaster"; import { FileUploadToast } from "../components/toasts/FileUploadToast"; +import { useQueryClient } from "@tanstack/react-query"; type FileUpload = FileWithPath & { parentId?: string; @@ -32,6 +33,7 @@ type Upload = { const useUpload = ({ item }: { item: Item }) => { const createFolder = useMutationCreateFolder(); + const queryClient = useQueryClient(); /** * TODO: Test. @@ -129,6 +131,9 @@ const useUpload = ({ item }: { item: Item }) => { }, { onSuccess: async (createdFolder) => { + queryClient.invalidateQueries({ + queryKey: ["items", parentItem.id], + }); folder.files.forEach((file) => { file.parentId = createdFolder.id; }); @@ -195,7 +200,7 @@ export const useUploadZone = ({ item }: { item: Item }) => { cloud_upload {t( - `explorer.actions.upload.toast${canUpload ? "_no_rights" : ""}`, + `explorer.actions.upload.toast${canUpload ? "" : "_no_rights"}`, { title: item?.title, }