This is an automated email from the ASF dual-hosted git repository.

jli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 1d141b2948 fix: Warning toasts when user drops folder item outside of 
dnd context (#38304)
1d141b2948 is described below

commit 1d141b2948eb2c33a1cb038ec5d99826be81115d
Author: Kamil Gabryjelski <[email protected]>
AuthorDate: Sat Feb 28 06:23:19 2026 +0100

    fix: Warning toasts when user drops folder item outside of dnd context 
(#38304)
---
 .../FoldersEditor/hooks/useDragHandlers.ts         | 58 ++++++++++++----------
 1 file changed, 33 insertions(+), 25 deletions(-)

diff --git 
a/superset-frontend/src/components/Datasource/FoldersEditor/hooks/useDragHandlers.ts
 
b/superset-frontend/src/components/Datasource/FoldersEditor/hooks/useDragHandlers.ts
index ddeca6884e..d5388f84ef 100644
--- 
a/superset-frontend/src/components/Datasource/FoldersEditor/hooks/useDragHandlers.ts
+++ 
b/superset-frontend/src/components/Datasource/FoldersEditor/hooks/useDragHandlers.ts
@@ -69,9 +69,6 @@ export function useDragHandlers({
   const [draggedFolderChildIds, setDraggedFolderChildIds] = useState<
     Set<string>
   >(new Set());
-  // Last non-null overId — fallback target when dropping in dead zones
-  const lastValidOverIdRef = useRef<UniqueIdentifier | null>(null);
-
   // Store the flattened items at drag start to keep them stable during drag
   // This prevents react-window from re-rendering due to flattenedItems 
reference changes
   const dragStartFlattenedItemsRef = useRef<FlattenedTreeItem[] | null>(null);
@@ -159,11 +156,23 @@ export function useDragHandlers({
     [childrenByParentId],
   );
 
+  const warnItemsOutsideFolders = useCallback(
+    (hasDraggedColumn: boolean, hasDraggedMetric: boolean) => {
+      if (hasDraggedColumn && hasDraggedMetric) {
+        addWarningToast(t('Columns and metrics should be inside folders'));
+      } else if (hasDraggedColumn) {
+        addWarningToast(t('Columns should be inside folders'));
+      } else if (hasDraggedMetric) {
+        addWarningToast(t('Metrics should be inside folders'));
+      }
+    },
+    [addWarningToast],
+  );
+
   const resetDragState = useCallback(() => {
     setActiveId(null);
     setOverId(null);
     offsetLeftRef.current = 0;
-    lastValidOverIdRef.current = null;
     setCurrentDropTargetId(null);
     setDraggedItemIds(new Set());
     setDraggedFolderChildIds(new Set());
@@ -238,9 +247,6 @@ export function useDragHandlers({
   const handleDragOver = useCallback(
     ({ over }: DragOverEvent) => {
       setOverId(over?.id ?? null);
-      if (over) {
-        lastValidOverIdRef.current = over.id;
-      }
 
       if (activeId && over) {
         if (typeof over.id === 'string' && over.id.endsWith('-empty')) {
@@ -270,22 +276,30 @@ export function useDragHandlers({
     const itemsBeingDragged = Array.from(draggedItemIds);
     const folderChildIds = draggedFolderChildIds;
     const finalOffsetLeft = offsetLeftRef.current;
-    // Capture fallback overId before reset (for dead-zone drops)
-    const fallbackOverId = lastValidOverIdRef.current;
     resetDragState();
 
-    // Folder drags only: hidden children create dead zones where over is null.
-    // Regular drags with null over just cancel.
-    const effectiveOver =
-      over ??
-      (folderChildIds.size > 0 && fallbackOverId
-        ? { id: fallbackOverId }
-        : null);
-    if (!effectiveOver || itemsBeingDragged.length === 0) {
+    if (itemsBeingDragged.length === 0) {
+      return;
+    }
+
+    if (!over) {
+      let hasDraggedColumn = false;
+      let hasDraggedMetric = false;
+      for (const id of itemsBeingDragged) {
+        const item = fullItemsByUuid.get(id);
+        if (item) {
+          if (item.type === FoldersEditorItemType.Column) {
+            hasDraggedColumn = true;
+          } else if (item.type === FoldersEditorItemType.Metric) {
+            hasDraggedMetric = true;
+          }
+        }
+      }
+      warnItemsOutsideFolders(hasDraggedColumn, hasDraggedMetric);
       return;
     }
 
-    let targetOverId = effectiveOver.id;
+    let targetOverId = over.id;
     let isEmptyDrop = false;
     if (typeof targetOverId === 'string' && targetOverId.endsWith('-empty')) {
       targetOverId = targetOverId.replace('-empty', '');
@@ -396,13 +410,7 @@ export function useDragHandlers({
 
     if (hasNonFolderItems) {
       if (!projectedPosition || !projectedPosition.parentId) {
-        if (hasDraggedColumn && hasDraggedMetric) {
-          addWarningToast(t('Columns and metrics should be inside folders'));
-        } else if (hasDraggedColumn) {
-          addWarningToast(t('Columns should be inside folders'));
-        } else {
-          addWarningToast(t('Metrics should be inside folders'));
-        }
+        warnItemsOutsideFolders(hasDraggedColumn, hasDraggedMetric);
         return;
       }
     }

Reply via email to