From 6dc5277120fec0d32b23853d0781a4184d89df0f Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Fri, 19 Dec 2025 01:20:29 -0800 Subject: [PATCH] fix(types): fix TypeScript errors in CollectionControl, DatasourceControl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add interfaces to CollectionControl with proper types for callbacks - Add interfaces to DatasourceControl with proper types - Fix CheckboxControl to accept ReactNode for label/description - Move static propTypes/defaultProps to class properties - Add type annotations to helper functions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../components/controls/CheckboxControl.tsx | 4 +- .../controls/CollectionControl/index.tsx | 11 ++-- .../controls/DatasourceControl/index.tsx | 61 ++++++++++++++----- 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/superset-frontend/src/explore/components/controls/CheckboxControl.tsx b/superset-frontend/src/explore/components/controls/CheckboxControl.tsx index 05feb1dcff0..e1c6c4ecbc9 100644 --- a/superset-frontend/src/explore/components/controls/CheckboxControl.tsx +++ b/superset-frontend/src/explore/components/controls/CheckboxControl.tsx @@ -23,9 +23,9 @@ import ControlHeader from '../ControlHeader'; interface CheckboxControlProps { value?: boolean; - label?: string; + label?: ReactNode; name?: string; - description?: string; + description?: ReactNode; hovered?: boolean; onChange?: (value: boolean) => void; } diff --git a/superset-frontend/src/explore/components/controls/CollectionControl/index.tsx b/superset-frontend/src/explore/components/controls/CollectionControl/index.tsx index 8d63323924e..8fd601e952d 100644 --- a/superset-frontend/src/explore/components/controls/CollectionControl/index.tsx +++ b/superset-frontend/src/explore/components/controls/CollectionControl/index.tsx @@ -73,13 +73,13 @@ const propTypes = { controlName: PropTypes.string.isRequired, }; -const defaultProps = { +const defaultProps: Partial = { label: null, description: null, onChange: () => {}, placeholder: t('Empty collection'), itemGenerator: () => ({ key: nanoid(11) }), - keyAccessor: o => o.key, + keyAccessor: (o: CollectionItem) => o.key ?? '', value: [], addTooltip: t('Add an item'), }; @@ -95,6 +95,10 @@ const SortableDragger = SortableHandle(() => ( )); class CollectionControl extends Component { + static propTypes = propTypes; + + static defaultProps = defaultProps; + constructor(props: CollectionControlProps) { super(props); this.onAdd = this.onAdd.bind(this); @@ -219,7 +223,4 @@ class CollectionControl extends Component { } } -CollectionControl.propTypes = propTypes; -CollectionControl.defaultProps = defaultProps; - export default withTheme(CollectionControl); diff --git a/superset-frontend/src/explore/components/controls/DatasourceControl/index.tsx b/superset-frontend/src/explore/components/controls/DatasourceControl/index.tsx index ed582b088eb..bf837cf2bb7 100644 --- a/superset-frontend/src/explore/components/controls/DatasourceControl/index.tsx +++ b/superset-frontend/src/explore/components/controls/DatasourceControl/index.tsx @@ -18,10 +18,10 @@ * under the License. */ -import { PureComponent } from 'react'; +import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { DatasourceType, SupersetClient, t } from '@superset-ui/core'; -import { css, styled, withTheme } from '@apache-superset/core/ui'; +import { DatasourceType, SupersetClient, t, Datasource } from '@superset-ui/core'; +import { css, styled, withTheme, type SupersetTheme } from '@apache-superset/core/ui'; import { getTemporalColumns } from '@superset-ui/chart-controls'; import { getUrlParam } from 'src/utils/urlUtils'; import { @@ -51,6 +51,34 @@ import { SaveDatasetModal } from 'src/SqlLab/components/SaveDatasetModal'; import { safeStringify } from 'src/utils/safeStringify'; import { Link } from 'react-router-dom'; +interface DatasourceControlActions { + changeDatasource: (datasource: Datasource) => void; + setControlValue: (name: string, value: unknown) => void; +} + +interface FormData { + granularity_sqla?: string; + [key: string]: unknown; +} + +interface DatasourceControlProps { + actions: DatasourceControlActions; + onChange?: () => void; + value?: string | null; + datasource: Datasource; + form_data: FormData; + isEditable?: boolean; + onDatasourceSave?: ((datasource: Datasource) => void) | null; + theme: SupersetTheme; +} + +interface DatasourceControlState { + showEditDatasourceModal: boolean; + showChangeDatasourceModal: boolean; + showSaveDatasetModal: boolean; + showDatasource?: boolean; +} + const propTypes = { actions: PropTypes.object.isRequired, onChange: PropTypes.func, @@ -68,7 +96,7 @@ const defaultProps = { isEditable: true, }; -const getDatasetType = datasource => { +const getDatasetType = (datasource: Datasource): string => { if (datasource.type === 'query') { return 'query'; } @@ -146,8 +174,8 @@ export const datasourceIconLookup = { }; // Render title for datasource with tooltip only if text is longer than VISIBLE_TITLE_LENGTH -export const renderDatasourceTitle = (displayString, tooltip) => - displayString?.length > VISIBLE_TITLE_LENGTH ? ( +export const renderDatasourceTitle = (displayString: string | undefined, tooltip: string) => + displayString?.length && displayString.length > VISIBLE_TITLE_LENGTH ? ( // Add a tooltip only for long names that will be visually truncated {displayString} @@ -159,12 +187,12 @@ export const renderDatasourceTitle = (displayString, tooltip) => ); // Different data source types use different attributes for the display title -export const getDatasourceTitle = datasource => { - if (datasource?.type === 'query') return datasource?.sql; +export const getDatasourceTitle = (datasource: Datasource | null | undefined): string => { + if (datasource?.type === 'query') return datasource?.sql || ''; return datasource?.name || ''; }; -const preventRouterLinkWhileMetaClicked = evt => { +const preventRouterLinkWhileMetaClicked = (evt: React.MouseEvent) => { if (evt.metaKey) { evt.preventDefault(); } else { @@ -172,8 +200,12 @@ const preventRouterLinkWhileMetaClicked = evt => { } }; -class DatasourceControl extends PureComponent { - constructor(props) { +class DatasourceControl extends PureComponent { + static propTypes = propTypes; + + static defaultProps = defaultProps; + + constructor(props: DatasourceControlProps) { super(props); this.state = { showEditDatasourceModal: false, @@ -182,7 +214,7 @@ class DatasourceControl extends PureComponent { }; } - onDatasourceSave = datasource => { + onDatasourceSave = (datasource: Datasource) => { this.props.actions.changeDatasource(datasource); const { temporalColumns, defaultTemporalColumn } = getTemporalColumns(datasource); @@ -238,7 +270,7 @@ class DatasourceControl extends PureComponent { })); }; - handleMenuItemClick = ({ key }) => { + handleMenuItemClick = ({ key }: { key: string }) => { switch (key) { case CHANGE_DATASET: this.toggleChangeDatasourceModal(); @@ -547,7 +579,4 @@ class DatasourceControl extends PureComponent { } } -DatasourceControl.propTypes = propTypes; -DatasourceControl.defaultProps = defaultProps; - export default withTheme(DatasourceControl);