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

asoare pushed a commit to branch alexandrusoare/fix/component-parent
in repository https://gitbox.apache.org/repos/asf/superset.git

commit ed7895c3941968df302a5a97869d0644f989321f
Author: alexandrusoare <[email protected]>
AuthorDate: Mon Feb 9 17:14:11 2026 +0200

    fix(componentParent): Newly created tabs don't show up in Scoping tab in 
filters edit mode
---
 .../src/dashboard/reducers/dashboardLayout.test.ts | 109 +++++++++++++++++++++
 .../src/dashboard/reducers/dashboardLayout.ts      |  12 ++-
 2 files changed, 120 insertions(+), 1 deletion(-)

diff --git a/superset-frontend/src/dashboard/reducers/dashboardLayout.test.ts 
b/superset-frontend/src/dashboard/reducers/dashboardLayout.test.ts
index 73b2610003f..55bf88720a2 100644
--- a/superset-frontend/src/dashboard/reducers/dashboardLayout.test.ts
+++ b/superset-frontend/src/dashboard/reducers/dashboardLayout.test.ts
@@ -422,14 +422,17 @@ describe('dashboardLayout reducer', () => {
       [DASHBOARD_GRID_ID]: {
         id: DASHBOARD_GRID_ID,
         children: ['child', 'child2'],
+        parents: [DASHBOARD_ROOT_ID],
       },
       child: {
         id: 'child',
         children: [],
+        parents: [DASHBOARD_ROOT_ID, DASHBOARD_GRID_ID],
       },
       child2: {
         id: 'child2',
         children: [],
+        parents: [DASHBOARD_ROOT_ID, DASHBOARD_GRID_ID],
       },
     });
   });
@@ -467,6 +470,112 @@ describe('dashboardLayout reducer', () => {
     expect(result[newId].type).toBe(ROW_TYPE);
   });
 
+  test('should update parents array when creating top-level tabs', () => {
+    const layout = {
+      [DASHBOARD_ROOT_ID]: {
+        id: DASHBOARD_ROOT_ID,
+        type: DASHBOARD_ROOT_TYPE,
+        children: [DASHBOARD_GRID_ID],
+        parents: [],
+      },
+      [DASHBOARD_GRID_ID]: {
+        id: DASHBOARD_GRID_ID,
+        type: DASHBOARD_GRID_TYPE,
+        children: ['row1'],
+        parents: [DASHBOARD_ROOT_ID],
+      },
+      row1: {
+        id: 'row1',
+        type: ROW_TYPE,
+        children: ['chart1'],
+        parents: [DASHBOARD_ROOT_ID, DASHBOARD_GRID_ID],
+      },
+      chart1: {
+        id: 'chart1',
+        type: CHART_TYPE,
+        children: [],
+        parents: [DASHBOARD_ROOT_ID, DASHBOARD_GRID_ID, 'row1'],
+      },
+    };
+
+    const dropResult = {
+      source: { id: NEW_COMPONENTS_SOURCE_ID, type: '' },
+      destination: {
+        id: DASHBOARD_ROOT_ID,
+        type: DASHBOARD_ROOT_TYPE,
+        index: 0,
+      },
+      dragging: { id: NEW_TABS_ID, type: TABS_TYPE },
+    };
+
+    const result = testReducer(layout, {
+      type: CREATE_TOP_LEVEL_TABS,
+      payload: { dropResult },
+    });
+
+    const tabsComponent = Object.values(result).find(
+      component => component.type === TABS_TYPE,
+    )!;
+
+    const tabComponent = Object.values(result).find(
+      component => component.type === TAB_TYPE,
+    )!;
+
+    // Verify parents are updated for moved components
+    expect(result.row1.parents).toContain(tabComponent.id);
+    expect(result.chart1.parents).toContain(tabComponent.id);
+  });
+
+  test('should update parents array when moving a component', () => {
+    const layout = {
+      [DASHBOARD_ROOT_ID]: {
+        id: DASHBOARD_ROOT_ID,
+        type: DASHBOARD_ROOT_TYPE,
+        children: [DASHBOARD_GRID_ID],
+        parents: [],
+      },
+      [DASHBOARD_GRID_ID]: {
+        id: DASHBOARD_GRID_ID,
+        type: DASHBOARD_GRID_TYPE,
+        children: ['row1', 'row2'],
+        parents: [DASHBOARD_ROOT_ID],
+      },
+      row1: {
+        id: 'row1',
+        type: ROW_TYPE,
+        children: ['chart1'],
+        parents: [DASHBOARD_ROOT_ID, DASHBOARD_GRID_ID],
+      },
+      row2: {
+        id: 'row2',
+        type: ROW_TYPE,
+        children: [],
+        parents: [DASHBOARD_ROOT_ID, DASHBOARD_GRID_ID],
+      },
+      chart1: {
+        id: 'chart1',
+        type: CHART_TYPE,
+        children: [],
+        parents: [DASHBOARD_ROOT_ID, DASHBOARD_GRID_ID, 'row1'],
+      },
+    };
+
+    const dropResult = {
+      source: { id: 'row1', type: ROW_TYPE, index: 0 },
+      destination: { id: 'row2', type: ROW_TYPE, index: 0 },
+      dragging: { id: 'chart1', type: CHART_TYPE },
+    };
+
+    const result = testReducer(layout, {
+      type: MOVE_COMPONENT,
+      payload: { dropResult },
+    });
+
+    // Chart should now have row2 as parent instead of row1
+    expect(result.chart1.parents).toContain('row2');
+    expect(result.chart1.parents).not.toContain('row1');
+  });
+
   test('recursivelyDeleteChildren should be error proof with bad inputs', () 
=> {
     /*
      ** The recursivelyDeleteChildren function was missing runtime safety 
checks before operating
diff --git a/superset-frontend/src/dashboard/reducers/dashboardLayout.ts 
b/superset-frontend/src/dashboard/reducers/dashboardLayout.ts
index 77840ee8462..aab6cd25a32 100644
--- a/superset-frontend/src/dashboard/reducers/dashboardLayout.ts
+++ b/superset-frontend/src/dashboard/reducers/dashboardLayout.ts
@@ -368,7 +368,17 @@ export default function layoutReducer(
 ): DashboardLayout {
   if (action.type in actionHandlers) {
     const handler = actionHandlers[action.type];
-    return handler(state, action);
+    const nextState = handler(state, action);
+
+    // Update parents list after any layout change
+    if (nextState !== state && nextState[DASHBOARD_ROOT_ID]) {
+      updateComponentParentsList({
+        currentComponent: nextState[DASHBOARD_ROOT_ID],
+        layout: nextState,
+      });
+    }
+
+    return nextState;
   }
 
   return state;

Reply via email to