sadpandajoe commented on code in PR #42483:
URL: https://github.com/apache/superset/pull/42483#discussion_r3725057643


##########
superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanelItem.tsx:
##########
@@ -188,10 +230,17 @@ const DatasourcePanelItem = ({
         ...style,
         paddingLeft: theme.sizeUnit * 4 + indentation,
         paddingRight: theme.sizeUnit * 4,
+        opacity: isRowInDraggedFolder ? 0.5 : undefined,
       }}
     >
       {item.type === 'header' && (
-        <SectionHeaderButton onClick={() => onToggleCollapse(folder.id)}>
+        <SectionHeaderButton
+          ref={setFolderDragRef}
+          onClick={() => onToggleCollapse(folder.id)}
+          style={{ cursor: folderDragItems.length ? 'grab' : undefined }}
+          {...folderDragAttributes}
+          {...folderDragListeners}

Review Comment:
   These keyboard drag listeners consume Enter and Space on the existing 
folder-header button, preventing keyboard users from toggling the folder and 
starting a drag instead. Could the drag listeners move to a dedicated handle so 
the collapse button keeps its native keyboard behavior?



##########
superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanelItem.tsx:
##########
@@ -175,9 +178,48 @@ const DatasourcePanelItem = ({
     [labelIsTruncated],
   );
 
-  if (!item) return null;
+  // Folder headers double as a drag source: dragging the label picks up every
+  // column/metric in the folder (and its subfolders). Hooks must run on every
+  // row regardless of type, so compute the folder up front and disable the
+  // draggable for non-header rows / empty folders.
+  const isFolderHeader = item?.type === 'header';
+  const folder = item ? folderMap.get(item.folderId) : undefined;
+  const folderDragItems = useMemo(
+    () => (isFolderHeader && folder ? collectFolderDragItems(folder) : []),
+    [isFolderHeader, folder],
+  );
+  const folderDragIds = useMemo(
+    () => (isFolderHeader && folder ? collectFolderIds(folder) : []),
+    [isFolderHeader, folder],
+  );
+  const {
+    attributes: folderDragAttributes,
+    listeners: folderDragListeners,
+    setNodeRef: setFolderDragRef,
+  } = useDraggable({
+    // Keyed by the flattened row index so every row (header, item, divider…)
+    // gets a unique draggable id — a folder's header and its child rows would
+    // otherwise collide on the shared folder id.
+    id: `datasource-folder-row-${index}`,
+    data: {
+      type: DndItemType.Folder,
+      name: folder?.name,
+      items: folderDragItems,

Review Comment:
   This payload includes fields that the semantic-layer compatibility response 
has disabled, so dragging a folder can add a dimension or metric that cannot be 
dragged individually and can produce an invalid query. Should the folder path 
apply the same `compatibleDimensions`/`compatibleMetrics` gate as 
`DatasourcePanelDragOption`?



##########
superset-frontend/src/explore/components/DatasourcePanel/folderDrag.ts:
##########
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { ColumnMeta, Metric } from '@superset-ui/chart-controls';
+import { FoldersEditorItemType } from 'src/components/Datasource/types';
+import { DndItemType } from '../DndItemType';
+import { DatasourcePanelDndItem, Folder, FolderItem } from './types';
+
+/**
+ * Map a single folder entry to the drag-item shape used by the control drop
+ * targets. Metrics become `DndItemType.Metric`, everything else a column.
+ */
+function toDndItem(item: FolderItem): DatasourcePanelDndItem {
+  return {
+    type:
+      item.type === FoldersEditorItemType.Metric
+        ? DndItemType.Metric
+        : DndItemType.Column,
+    // The runtime object carries the full ColumnMeta/Metric (see
+    // transformDatasourceWithFolders spreading `...column`/`...metric`), which
+    // is what the drop handlers expect.
+    value: item as ColumnMeta | Metric,
+  };
+}
+
+/**
+ * Flatten a folder into the list of draggable columns/metrics it contains,
+ * descending into subfolders so dragging a parent folder brings everything
+ * nested under it.
+ */
+export function collectFolderDragItems(
+  folder: Folder,
+): DatasourcePanelDndItem[] {
+  const items = folder.items.map(toDndItem);

Review Comment:
   When datasource search is active, this `Folder` was built from the filtered 
column/metric arrays, so dragging its header adds only the visible matches 
rather than the entire folder promised by this feature. Should the drag payload 
be built from the unfiltered folder contents while the rendered rows remain 
filtered?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to