This is an automated email from the ASF dual-hosted git repository. rusackas pushed a commit to branch chore/ts-migration-dashboard in repository https://gitbox.apache.org/repos/asf/superset.git
commit 7e7f8281f8a1b40bee6b78869ede523931a7f08c Author: Evan Rusackas <[email protected]> AuthorDate: Sun Feb 1 16:39:34 2026 +0100 refactor(dashboard): consolidate duplicate type definitions across utility files Replace local DashboardComponent, ComponentsMap, LayoutEntity, LayoutMap, ComponentMeta, and DropResult type definitions with shared types from types.ts and dragDroppableConfig.ts. Adds DashboardComponent interface (loose type for utilities) and DashboardComponentMap to types.ts, makes LayoutItemMeta fields optional, and has DashboardEntity extend the shared DashboardComponent type. Net reduction of ~123 lines of duplicate code. Co-Authored-By: Claude Opus 4.5 <[email protected]> --- .../FiltersConfigForm/FilterScope/utils.ts | 6 +-- .../dashboard/components/nativeFilters/state.ts | 2 +- .../src/dashboard/reducers/dashboardLayout.ts | 26 +---------- superset-frontend/src/dashboard/types.ts | 21 +++++++-- .../dashboard/util/getComponentWidthFromDrop.ts | 41 ++--------------- .../dashboard/util/getDetailedComponentWidth.ts | 25 ++-------- .../src/dashboard/util/getFilterScopeNodesTree.ts | 21 ++------- .../src/dashboard/util/newComponentFactory.ts | 28 +++--------- .../src/dashboard/util/newEntitiesFromDrop.ts | 53 ++++------------------ 9 files changed, 50 insertions(+), 173 deletions(-) diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts index 432be5d8eb5..8864c256164 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.ts @@ -115,7 +115,7 @@ export const buildTree = ( ) { const title = buildTreeLeafTitle( getNodeTitle(node), - initiallyExcludedCharts?.includes?.(node.meta?.chartId), + initiallyExcludedCharts?.includes?.(node.meta?.chartId as number), t( "This chart might be incompatible with the filter (datasets don't match)", ), @@ -202,7 +202,7 @@ const checkTreeItem = ( ); if ( layout[item]?.type === CHART_TYPE && - !excluded.includes(layout[item]?.meta.chartId) + !excluded.includes(layout[item]?.meta.chartId as number) ) { checkedItems.push(item); } @@ -306,7 +306,7 @@ export const findFilterScope = ( value.type === CHART_TYPE && [DASHBOARD_ROOT_ID, ...parents]?.find(parent => isExcluded(parent, key)) ) { - excluded.push(value.meta.chartId); + excluded.push(value.meta.chartId as number); } }); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/state.ts index 431994da6f8..f95c1bae4ef 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/state.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/state.ts @@ -86,7 +86,7 @@ const selectDashboardChartIds = createSelector( new Set( Object.values(dashboardLayout) .filter(item => item.type === CHART_TYPE && item.meta?.chartId) - .map(item => item.meta.chartId), + .map(item => item.meta.chartId!), ), ); diff --git a/superset-frontend/src/dashboard/reducers/dashboardLayout.ts b/superset-frontend/src/dashboard/reducers/dashboardLayout.ts index 75c891ae462..77840ee8462 100644 --- a/superset-frontend/src/dashboard/reducers/dashboardLayout.ts +++ b/superset-frontend/src/dashboard/reducers/dashboardLayout.ts @@ -45,31 +45,7 @@ import { import { HYDRATE_DASHBOARD } from '../actions/hydrate'; import { DashboardLayout } from '../types'; - -interface DropResultSource { - id: string; - type?: string; - index: number; -} - -interface DropResultDestination { - id: string; - type?: string; - index: number; -} - -interface DropResultDragging { - id: string; - type: string; - meta?: Record<string, unknown>; -} - -interface DropResult { - source: DropResultSource; - destination: DropResultDestination; - dragging: DropResultDragging; - position?: string; -} +import { DropResult } from '../components/dnd/dragDroppableConfig'; interface DashboardLayoutAction { type: string; diff --git a/superset-frontend/src/dashboard/types.ts b/superset-frontend/src/dashboard/types.ts index fdac5cee321..bd1076247a3 100644 --- a/superset-frontend/src/dashboard/types.ts +++ b/superset-frontend/src/dashboard/types.ts @@ -238,15 +238,16 @@ type ComponentTypesKeys = keyof typeof componentTypes; export type ComponentType = (typeof componentTypes)[ComponentTypesKeys]; export type LayoutItemMeta = { - chartId: number; + chartId?: number; defaultText?: string; - height: number; + height?: number; placeholder?: string; sliceName?: string; sliceNameOverride?: string; text?: string; - uuid: string; - width: number; + uuid?: string; + width?: number; + headerSize?: string; /** Markdown source code for markdown components */ code?: string; /** Background style value for columns and rows */ @@ -264,6 +265,18 @@ export type LayoutItem = { meta: LayoutItemMeta; }; +/** Loose component type used by utility and factory functions */ +export interface DashboardComponent { + id: string; + type: string; + children: string[]; + parents?: string[]; + meta: LayoutItemMeta; +} + +/** Map of dashboard components keyed by ID */ +export type DashboardComponentMap = { [id: string]: DashboardComponent }; + type ActiveFilter = { filterType?: string; targets: Partial<NativeFilterTarget>[]; diff --git a/superset-frontend/src/dashboard/util/getComponentWidthFromDrop.ts b/superset-frontend/src/dashboard/util/getComponentWidthFromDrop.ts index fee2c27c352..7a64e4a2c7e 100644 --- a/superset-frontend/src/dashboard/util/getComponentWidthFromDrop.ts +++ b/superset-frontend/src/dashboard/util/getComponentWidthFromDrop.ts @@ -20,44 +20,12 @@ import { NEW_COMPONENTS_SOURCE_ID } from './constants'; import findParentId from './findParentId'; import getDetailedComponentWidth from './getDetailedComponentWidth'; import newComponentFactory from './newComponentFactory'; - -interface DropSource { - id: string; - type?: string; - index?: number; -} - -interface DraggingInfo { - id: string; - type: string; - meta?: Record<string, unknown>; -} - -interface DropResultForWidth { - source: DropSource; - destination: DropSource; - dragging: DraggingInfo; -} - -interface ComponentsMapEntry { - id: string; - type?: string; - children: string[]; - parents?: string[]; - meta?: { - width?: number; - height?: number; - [key: string]: unknown; - }; -} - -interface ComponentsMap { - [id: string]: ComponentsMapEntry; -} +import { DashboardComponentMap } from '../types'; +import { DropResult } from '../components/dnd/dragDroppableConfig'; interface GetComponentWidthFromDropParams { - dropResult: DropResultForWidth; - layout: ComponentsMap; + dropResult: DropResult; + layout: DashboardComponentMap; } export default function getComponentWidthFromDrop({ @@ -65,6 +33,7 @@ export default function getComponentWidthFromDrop({ layout: components, }: GetComponentWidthFromDropParams): number | undefined { const { source, destination, dragging } = dropResult; + if (!destination) return undefined; const isNewComponent = source.id === NEW_COMPONENTS_SOURCE_ID; const component = isNewComponent diff --git a/superset-frontend/src/dashboard/util/getDetailedComponentWidth.ts b/superset-frontend/src/dashboard/util/getDetailedComponentWidth.ts index a154cb6a46e..820f5da5f5a 100644 --- a/superset-frontend/src/dashboard/util/getDetailedComponentWidth.ts +++ b/superset-frontend/src/dashboard/util/getDetailedComponentWidth.ts @@ -25,26 +25,11 @@ import { CHART_TYPE, DYNAMIC_TYPE, } from './componentTypes'; - -interface DashboardComponent { - id: string; - type?: string; - children: string[]; - parents?: string[]; - meta?: { - width?: number; - height?: number; - [key: string]: unknown; - }; -} - -interface ComponentsMap { - [id: string]: DashboardComponent; -} +import { DashboardComponent, DashboardComponentMap } from '../types'; interface GetTotalChildWidthParams { id: string; - components: ComponentsMap; + components: DashboardComponentMap; } interface DetailedWidth { @@ -56,7 +41,7 @@ interface DetailedWidth { interface GetDetailedComponentWidthParams { id?: string | null; component?: DashboardComponent; - components?: ComponentsMap; + components?: DashboardComponentMap; } function getTotalChildWidth({ @@ -69,8 +54,8 @@ function getTotalChildWidth({ let width = 0; (component.children || []).forEach(childId => { - const child = components[childId] || {}; - width += child.meta?.width || 0; + const child = components[childId]; + width += child?.meta?.width || 0; }); return width; diff --git a/superset-frontend/src/dashboard/util/getFilterScopeNodesTree.ts b/superset-frontend/src/dashboard/util/getFilterScopeNodesTree.ts index c3c251df15f..e5bf06421fb 100644 --- a/superset-frontend/src/dashboard/util/getFilterScopeNodesTree.ts +++ b/superset-frontend/src/dashboard/util/getFilterScopeNodesTree.ts @@ -21,22 +21,7 @@ import { t } from '@apache-superset/core/ui'; import { DASHBOARD_ROOT_ID } from './constants'; import { CHART_TYPE, DASHBOARD_ROOT_TYPE, TAB_TYPE } from './componentTypes'; - -interface DashboardComponent { - id: string; - type: string; - children?: string[]; - meta?: { - chartId?: number; - sliceName?: string; - text?: string; - [key: string]: unknown; - }; -} - -interface ComponentsMap { - [id: string]: DashboardComponent; -} +import { DashboardComponent, DashboardComponentMap } from '../types'; type FilterField = string | { chartId: number; column: string }; @@ -50,7 +35,7 @@ interface ScopeTreeNode { interface TraverseParams { currentNode?: DashboardComponent; - components?: ComponentsMap; + components?: DashboardComponentMap; filterFields?: FilterField[]; selectedChartId?: number; } @@ -126,7 +111,7 @@ function traverse({ } interface GetFilterScopeNodesTreeParams { - components?: ComponentsMap; + components?: DashboardComponentMap; filterFields?: FilterField[]; selectedChartId?: number; } diff --git a/superset-frontend/src/dashboard/util/newComponentFactory.ts b/superset-frontend/src/dashboard/util/newComponentFactory.ts index 5c207a14beb..28e857015f8 100644 --- a/superset-frontend/src/dashboard/util/newComponentFactory.ts +++ b/superset-frontend/src/dashboard/util/newComponentFactory.ts @@ -38,30 +38,16 @@ import { GRID_COLUMN_COUNT, } from './constants'; -interface ComponentMeta { - width?: number; - height?: number; - background?: string; - text?: string; - headerSize?: string; - defaultText?: string; - placeholder?: string; - chartId?: number; - sliceName?: string; - sliceNameOverride?: string; - uuid?: string; - [key: string]: unknown; -} +import { + DashboardComponent, + LayoutItemMeta, +} from '../types'; -export interface DashboardEntity { - type: string; - id: string; - children: string[]; +export interface DashboardEntity extends DashboardComponent { parents: string[]; - meta: ComponentMeta; } -const typeToDefaultMetaData: Record<string, ComponentMeta | null> = { +const typeToDefaultMetaData: Record<string, LayoutItemMeta | null> = { [CHART_TYPE]: { width: GRID_DEFAULT_CHART_WIDTH, height: 50 }, [COLUMN_TYPE]: { width: GRID_DEFAULT_CHART_WIDTH, @@ -93,7 +79,7 @@ function generateId(type: string): string { export default function entityFactory( type: string, - meta?: ComponentMeta, + meta?: LayoutItemMeta, parents: string[] = [], ): DashboardEntity { return { diff --git a/superset-frontend/src/dashboard/util/newEntitiesFromDrop.ts b/superset-frontend/src/dashboard/util/newEntitiesFromDrop.ts index a1468764c9b..5307abdf209 100644 --- a/superset-frontend/src/dashboard/util/newEntitiesFromDrop.ts +++ b/superset-frontend/src/dashboard/util/newEntitiesFromDrop.ts @@ -18,61 +18,24 @@ */ import componentIsResizable from './componentIsResizable'; import shouldWrapChildInRow from './shouldWrapChildInRow'; -import newComponentFactory, { - type DashboardEntity, -} from './newComponentFactory'; +import newComponentFactory from './newComponentFactory'; import getComponentWidthFromDrop from './getComponentWidthFromDrop'; import { ROW_TYPE, TABS_TYPE, TAB_TYPE } from './componentTypes'; - -interface DraggingInfo { - id: string; - type: string; - meta?: Record<string, unknown>; -} - -interface DropDestination { - id: string; - type: string; - index: number; -} - -interface DropResultForEntities { - source: { - id: string; - type?: string; - index: number; - }; - dragging: DraggingInfo; - destination: DropDestination; -} - -interface LayoutEntity { - id: string; - type: string; - children: string[]; - parents?: string[]; - meta?: { - width?: number; - height?: number; - [key: string]: unknown; - }; -} - -interface LayoutMap { - [id: string]: LayoutEntity; -} +import { DashboardComponent, DashboardComponentMap } from '../types'; +import { DropResult } from '../components/dnd/dragDroppableConfig'; interface NewEntitiesFromDropParams { - dropResult: DropResultForEntities; - layout: LayoutMap; + dropResult: DropResult; + layout: DashboardComponentMap; } export default function newEntitiesFromDrop({ dropResult, layout, -}: NewEntitiesFromDropParams): Record<string, DashboardEntity | LayoutEntity> { +}: NewEntitiesFromDropParams): Record<string, DashboardComponent> { const { dragging, destination } = dropResult; + if (!destination) return {}; const dragType = dragging.type; const dropEntity = layout[destination.id]; @@ -90,7 +53,7 @@ export default function newEntitiesFromDrop({ childType: dragType, }); - const newEntities: Record<string, DashboardEntity | LayoutEntity> = { + const newEntities: Record<string, DashboardComponent> = { [newDropChild.id]: newDropChild, };
