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;
