From 624f99414f7c81da8883e8a842879927bd3c97e8 Mon Sep 17 00:00:00 2001 From: Jesse Yang Date: Thu, 18 Feb 2021 08:48:05 -1000 Subject: [PATCH 01/18] refactor(explore): convert ControlPanelsContainer to typescript --- .../src/explore/actions/exploreActions.ts | 8 +- .../src/explore/components/Control.tsx | 3 +- ...ntainer.jsx => ControlPanelsContainer.tsx} | 155 +++++++++--------- .../{ControlRow.jsx => ControlRow.tsx} | 19 +-- .../components/ExploreViewContainer.jsx | 3 - .../DateFilterControl/DateFilterControl.tsx | 12 +- superset-frontend/src/explore/controls.jsx | 5 +- .../src/explore/reducers/exploreReducer.js | 6 - ...{getInitialState.js => getInitialState.ts} | 23 ++- superset-frontend/src/types/Chart.ts | 3 +- superset-frontend/src/types/bootstrapTypes.ts | 9 + 11 files changed, 137 insertions(+), 109 deletions(-) rename superset-frontend/src/explore/components/{ControlPanelsContainer.jsx => ControlPanelsContainer.tsx} (73%) rename superset-frontend/src/explore/components/{ControlRow.jsx => ControlRow.tsx} (76%) rename superset-frontend/src/explore/reducers/{getInitialState.js => getInitialState.ts} (79%) diff --git a/superset-frontend/src/explore/actions/exploreActions.ts b/superset-frontend/src/explore/actions/exploreActions.ts index 4923ae3174d0..7ebfc45e4263 100644 --- a/superset-frontend/src/explore/actions/exploreActions.ts +++ b/superset-frontend/src/explore/actions/exploreActions.ts @@ -99,7 +99,7 @@ export const SET_FIELD_VALUE = 'SET_FIELD_VALUE'; export function setControlValue( controlName: string, value: any, - validationErrors: any[], + validationErrors?: any[], ) { return { type: SET_FIELD_VALUE, controlName, value, validationErrors }; } @@ -109,11 +109,6 @@ export function setExploreControls(formData: QueryFormData) { return { type: SET_EXPLORE_CONTROLS, formData }; } -export const REMOVE_CONTROL_PANEL_ALERT = 'REMOVE_CONTROL_PANEL_ALERT'; -export function removeControlPanelAlert() { - return { type: REMOVE_CONTROL_PANEL_ALERT }; -} - export const UPDATE_CHART_TITLE = 'UPDATE_CHART_TITLE'; export function updateChartTitle(sliceName: string) { return { type: UPDATE_CHART_TITLE, sliceName }; @@ -154,7 +149,6 @@ export const exploreActions = { saveFaveStar, setControlValue, setExploreControls, - removeControlPanelAlert, updateChartTitle, createNewSlice, sliceUpdated, diff --git a/superset-frontend/src/explore/components/Control.tsx b/superset-frontend/src/explore/components/Control.tsx index f1b6925bd693..6b1e7fa8b885 100644 --- a/superset-frontend/src/explore/components/Control.tsx +++ b/superset-frontend/src/explore/components/Control.tsx @@ -17,7 +17,7 @@ * under the License. */ import React, { ReactNode } from 'react'; -import { ControlType } from '@superset-ui/chart-controls'; +import { ControlStateMapping, ControlType } from '@superset-ui/chart-controls'; import { JsonValue, QueryFormData } from '@superset-ui/core'; import { ExploreActions } from '../actions/exploreActions'; import controlMap from './controls'; @@ -35,6 +35,7 @@ export type ControlProps = { tooltipOnClick?: () => ReactNode; places?: number; rightNode?: ReactNode; + controls?: ControlStateMapping; formData?: QueryFormData | null; value?: JsonValue; validationErrors?: any[]; diff --git a/superset-frontend/src/explore/components/ControlPanelsContainer.jsx b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx similarity index 73% rename from superset-frontend/src/explore/components/ControlPanelsContainer.jsx rename to superset-frontend/src/explore/components/ControlPanelsContainer.tsx index cc61ab2f1ca7..9afd04a3c77d 100644 --- a/superset-frontend/src/explore/components/ControlPanelsContainer.jsx +++ b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx @@ -18,30 +18,49 @@ */ /* eslint camelcase: 0 */ import React from 'react'; -import PropTypes from 'prop-types'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; -import { t, styled, getChartControlPanelRegistry } from '@superset-ui/core'; +import { + t, + styled, + getChartControlPanelRegistry, + QueryFormData, + DatasourceType, +} from '@superset-ui/core'; import Tabs from 'src/common/components/Tabs'; import Alert from 'src/components/Alert'; import Collapse from 'src/common/components/Collapse'; import { PluginContext } from 'src/components/DynamicPlugins'; import Loading from 'src/components/Loading'; -import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls'; +import { + ControlPanelSectionConfig, + ControlState, + CustomControlItem, + ExpandedControlItem, + InfoTooltipWithTrigger, +} from '@superset-ui/chart-controls'; import ControlRow from './ControlRow'; import Control from './Control'; import { sectionsToRender } from '../controlUtils'; -import { exploreActions } from '../actions/exploreActions'; +import { ExploreActions, exploreActions } from '../actions/exploreActions'; +import { InitialExploreState } from '../reducers/getInitialState'; -const propTypes = { - actions: PropTypes.object.isRequired, - alert: PropTypes.string, - datasource_type: PropTypes.string.isRequired, - exploreState: PropTypes.object.isRequired, - controls: PropTypes.object.isRequired, - form_data: PropTypes.object.isRequired, - isDatasourceMetaLoading: PropTypes.bool.isRequired, +type ControlPanelsContainerProps = { + actions: ExploreActions; + alert: string; + datasource_type: DatasourceType; + exploreState: Record; + controls: Record; + form_data: QueryFormData; + isDatasourceMetaLoading: boolean; +}; + +type ExpandedControlPanelSectionConfig = Omit< + ControlPanelSectionConfig, + 'controlSetRows' +> & { + controlSetRows: ExpandedControlItem[][]; }; const Styles = styled.div` @@ -80,19 +99,18 @@ const ControlPanelsTabs = styled(Tabs)` height: 100%; } `; -class ControlPanelsContainer extends React.Component { + +class ControlPanelsContainer extends React.Component { // trigger updates to the component when async plugins load static contextType = PluginContext; - constructor(props) { + constructor(props: ControlPanelsContainerProps) { super(props); - - this.removeAlert = this.removeAlert.bind(this); this.renderControl = this.renderControl.bind(this); this.renderControlPanelSection = this.renderControlPanelSection.bind(this); } - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps: ControlPanelsContainerProps) { const { actions: { setControlValue }, } = this.props; @@ -107,32 +125,29 @@ class ControlPanelsContainer extends React.Component { ]; Object.entries(this.props.controls).forEach(([controlName, control]) => { const { type, default: defaultValue } = control; - if (defaultValues.includes(type)) { + if (typeof type === 'string' && defaultValues.includes(type)) { setControlValue(controlName, defaultValue); } }); } } - sectionsToRender() { + sectionsToRender(): ExpandedControlPanelSectionConfig[] { return sectionsToRender( this.props.form_data.viz_type, this.props.datasource_type, ); } - sectionsToExpand(sections) { + sectionsToExpand(sections: ControlPanelSectionConfig[]) { return sections.reduce( - (acc, cur) => (cur.expanded ? [...acc, cur.label] : acc), - [], + (acc, section) => + section.expanded ? [...acc, String(section.label)] : acc, + [] as string[], ); } - removeAlert() { - this.props.actions.removeControlPanelAlert(); - } - - renderControl({ name, config }) { + renderControl({ name, config }: CustomControlItem) { const { actions, controls, form_data: formData } = this.props; const { visibility } = config; @@ -144,11 +159,9 @@ class ControlPanelsContainer extends React.Component { ...controls[name], name, }; - const { - validationErrors, - provideFormDataToProps, - ...restProps - } = controlData; + const { validationErrors, ...restProps } = controlData as ControlState & { + validationErrors?: any[]; + }; // if visibility check says the config is not visible, don't render it if (visibility && !visibility.call(config, this.props, controlData)) { @@ -160,30 +173,41 @@ class ControlPanelsContainer extends React.Component { name={name} validationErrors={validationErrors} actions={actions} - formData={provideFormDataToProps ? formData : null} - datasource={formData?.datasource} + controls={controls} + formData={formData} {...restProps} /> ); } - renderControlPanelSection(section) { + renderControlPanelSection(section: ExpandedControlPanelSectionConfig) { const { controls } = this.props; const { label, description } = section; const hasErrors = section.controlSetRows.some(rows => - rows.some( - s => - controls[s] && - controls[s].validationErrors && - controls[s].validationErrors.length > 0, - ), + rows.some(item => { + const controlName = + typeof item === 'string' + ? item + : item && 'name' in item + ? item.name + : null; + return ( + controlName && + controlName in controls && + controls[controlName].validationErrors && + controls[controlName].validationErrors.length > 0 + ); + }), ); const PanelHeader = () => ( {label}{' '} {description && ( - + )} {hasErrors && ( {section.controlSetRows.map((controlSets, i) => { const renderedControls = controlSets @@ -229,7 +253,6 @@ class ControlPanelsContainer extends React.Component { return ( ); @@ -247,8 +270,8 @@ class ControlPanelsContainer extends React.Component { return ; } - const querySectionsToRender = []; - const displaySectionsToRender = []; + const querySectionsToRender: ExpandedControlPanelSectionConfig[] = []; + const displaySectionsToRender: ExpandedControlPanelSectionConfig[] = []; this.sectionsToRender().forEach(section => { // if at least one control in the section is not `renderTrigger` // or asks to be displayed at the Data tab @@ -258,6 +281,7 @@ class ControlPanelsContainer extends React.Component { rows.some( control => control && + 'config' in control && control.config && (!control.config.renderTrigger || control.config.tabOverride === 'data'), @@ -277,14 +301,6 @@ class ControlPanelsContainer extends React.Component { ); return ( - {this.props.alert && ( - - )} - {props.controls.map((control, i) => ( + {controls.map((control, i) => (
{control}
@@ -37,6 +37,3 @@ function ControlSetRow(props) { ); } - -ControlSetRow.propTypes = propTypes; -export default ControlSetRow; diff --git a/superset-frontend/src/explore/components/ExploreViewContainer.jsx b/superset-frontend/src/explore/components/ExploreViewContainer.jsx index 71d163aa7265..cd72ac7214cb 100644 --- a/superset-frontend/src/explore/components/ExploreViewContainer.jsx +++ b/superset-frontend/src/explore/components/ExploreViewContainer.jsx @@ -222,10 +222,7 @@ function ExploreViewContainer(props) { } function onQuery() { - // remove alerts when query - props.actions.removeControlPanelAlert(); props.actions.triggerQuery(true, props.chart.id); - addHistory(); } diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterControl.tsx b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterControl.tsx index 0e84bc3ee7b3..60b4c501d018 100644 --- a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterControl.tsx +++ b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterControl.tsx @@ -165,16 +165,22 @@ const IconWrapper = styled.span` } `; -interface DateFilterLabelProps { +interface DateFilterControlProps { name: string; onChange: (timeRange: string) => void; value?: string; endpoints?: TimeRangeEndpoints; datasource?: string; + formData?: { datasource: string }; } -export default function DateFilterControl(props: DateFilterLabelProps) { - const { value = 'Last week', endpoints, onChange, datasource } = props; +export default function DateFilterControl(props: DateFilterControlProps) { + const { + value = 'Last week', + endpoints, + onChange, + formData: { datasource } = {}, + } = props; const [actualTimeRange, setActualTimeRange] = useState(value); const [show, setShow] = useState(false); diff --git a/superset-frontend/src/explore/controls.jsx b/superset-frontend/src/explore/controls.jsx index dfbfd21f567f..a133b51f16ef 100644 --- a/superset-frontend/src/explore/controls.jsx +++ b/superset-frontend/src/explore/controls.jsx @@ -355,8 +355,8 @@ export const controls = { "using the engine's local timezone. Note one can explicitly set the timezone " + 'per the ISO 8601 format if specifying either the start and/or end time.', ), - mapStateToProps: state => ({ - endpoints: state.form_data ? state.form_data.time_range_endpoints : null, + mapStateToProps: ({ form_data }) => ({ + endpoints: form_data?.time_range_endpoints, }), }, @@ -474,7 +474,6 @@ export const controls = { savedMetrics: state.datasource ? state.datasource.metrics : [], datasource: state.datasource, }), - provideFormDataToProps: true, }, color_scheme: { diff --git a/superset-frontend/src/explore/reducers/exploreReducer.js b/superset-frontend/src/explore/reducers/exploreReducer.js index 307672738975..aa79e8243050 100644 --- a/superset-frontend/src/explore/reducers/exploreReducer.js +++ b/superset-frontend/src/explore/reducers/exploreReducer.js @@ -85,12 +85,6 @@ export default function exploreReducer(state = {}, action) { datasources: action.datasources, }; }, - [actions.REMOVE_CONTROL_PANEL_ALERT]() { - return { - ...state, - controlPanelAlert: null, - }; - }, [actions.SET_FIELD_VALUE]() { const new_form_data = state.form_data; const { controlName, value, validationErrors } = action; diff --git a/superset-frontend/src/explore/reducers/getInitialState.js b/superset-frontend/src/explore/reducers/getInitialState.ts similarity index 79% rename from superset-frontend/src/explore/reducers/getInitialState.js rename to superset-frontend/src/explore/reducers/getInitialState.ts index 07743401da15..632be593f94f 100644 --- a/superset-frontend/src/explore/reducers/getInitialState.js +++ b/superset-frontend/src/explore/reducers/getInitialState.ts @@ -25,8 +25,26 @@ import { getFormDataFromControls, applyMapStateToPropsToControl, } from '../controlUtils'; +import { Datasource, DatasourceType, JsonObject, QueryFormData } from '@superset-ui/core'; +import { Slice } from 'src/types/Chart'; +import { CommonBootstrapData } from 'src/types/bootstrapTypes'; -export default function getInitialState(bootstrapData) { +export interface ExlorePageBootstrapData extends JsonObject { + can_add: boolean; + can_download: boolean; + can_overwrite: boolean; + datasource: Datasource; + form_data: QueryFormData; + datasource_id: number; + datasource_type: DatasourceType; + slice: Slice | null; + standalone: boolean; + user_id: number; + forced_height: string | null; + common: CommonBootstrapData; +} + +export default function getInitialState(bootstrapData: ExlorePageBootstrapData) { const { form_data: rawFormData } = bootstrapData; const { slice } = bootstrapData; const sliceName = slice ? slice.slice_name : null; @@ -41,6 +59,7 @@ export default function getInitialState(bootstrapData) { filterColumnOpts: [], isDatasourceMetaLoading: false, isStarred: false, + controls: {}, }; const controls = getControlsState(bootstrappedState, rawFormData); bootstrappedState.controls = controls; @@ -88,3 +107,5 @@ export default function getInitialState(bootstrapData) { ), }; } + +export type InitialExploreState = ReturnType; diff --git a/superset-frontend/src/types/Chart.ts b/superset-frontend/src/types/Chart.ts index cf78dab43eb8..a2e9f7dbb516 100644 --- a/superset-frontend/src/types/Chart.ts +++ b/superset-frontend/src/types/Chart.ts @@ -21,6 +21,7 @@ * The Chart model as returned from the API */ +import { QueryFormData } from '@superset-ui/core'; import Owner from './Owner'; export interface Chart { @@ -45,7 +46,7 @@ export type Slice = { slice_name: string; description: string | null; cache_timeout: number | null; - url?: string; + form_data: QueryFormData; }; export default Chart; diff --git a/superset-frontend/src/types/bootstrapTypes.ts b/superset-frontend/src/types/bootstrapTypes.ts index cb8fb1ef31a4..7ef7caaab482 100644 --- a/superset-frontend/src/types/bootstrapTypes.ts +++ b/superset-frontend/src/types/bootstrapTypes.ts @@ -1,3 +1,5 @@ +import { JsonObject, Locale } from '@superset-ui/core'; + /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -42,3 +44,10 @@ export type Dashboard = { creator?: string; creator_url?: string; }; + +export interface CommonBootstrapData { + flash_messages: string[][]; + conf: JsonObject; + locale: Locale; + feature_flags: Record; +} From 2f00a4f7166f9d228c0a89ac51d5cf509193ba24 Mon Sep 17 00:00:00 2001 From: Jesse Yang Date: Thu, 18 Feb 2021 08:54:13 -1000 Subject: [PATCH 02/18] Fix lint errors --- superset-frontend/.eslintrc.js | 1 + superset-frontend/src/explore/controls.jsx | 4 ++-- .../src/explore/reducers/getInitialState.ts | 23 ++++++++++++------- superset-frontend/src/types/Chart.ts | 2 +- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js index 469709528089..0d9531aa951b 100644 --- a/superset-frontend/.eslintrc.js +++ b/superset-frontend/.eslintrc.js @@ -226,6 +226,7 @@ module.exports = { 'no-mixed-operators': 0, 'no-multi-assign': 0, 'no-multi-spaces': 0, + 'no-nested-ternary': 0, 'no-prototype-builtins': 0, 'no-restricted-properties': 0, 'no-restricted-imports': [ diff --git a/superset-frontend/src/explore/controls.jsx b/superset-frontend/src/explore/controls.jsx index a133b51f16ef..659da282600b 100644 --- a/superset-frontend/src/explore/controls.jsx +++ b/superset-frontend/src/explore/controls.jsx @@ -355,8 +355,8 @@ export const controls = { "using the engine's local timezone. Note one can explicitly set the timezone " + 'per the ISO 8601 format if specifying either the start and/or end time.', ), - mapStateToProps: ({ form_data }) => ({ - endpoints: form_data?.time_range_endpoints, + mapStateToProps: ({ form_data: formData }) => ({ + endpoints: formData?.time_range_endpoints, }), }, diff --git a/superset-frontend/src/explore/reducers/getInitialState.ts b/superset-frontend/src/explore/reducers/getInitialState.ts index 632be593f94f..7979395bcaed 100644 --- a/superset-frontend/src/explore/reducers/getInitialState.ts +++ b/superset-frontend/src/explore/reducers/getInitialState.ts @@ -17,17 +17,22 @@ * under the License. */ import shortid from 'shortid'; +import { + Datasource, + DatasourceType, + JsonObject, + QueryFormData, +} from '@superset-ui/core'; +import { Slice } from 'src/types/Chart'; +import { CommonBootstrapData } from 'src/types/bootstrapTypes'; -import getToastsFromPyFlashMessages from '../../messageToasts/utils/getToastsFromPyFlashMessages'; -import { getChartKey } from '../exploreUtils'; -import { getControlsState } from '../store'; +import getToastsFromPyFlashMessages from 'src/messageToasts/utils/getToastsFromPyFlashMessages'; +import { getChartKey } from 'src/explore/exploreUtils'; +import { getControlsState } from 'src/explore/store'; import { getFormDataFromControls, applyMapStateToPropsToControl, -} from '../controlUtils'; -import { Datasource, DatasourceType, JsonObject, QueryFormData } from '@superset-ui/core'; -import { Slice } from 'src/types/Chart'; -import { CommonBootstrapData } from 'src/types/bootstrapTypes'; +} from 'src/explore/controlUtils'; export interface ExlorePageBootstrapData extends JsonObject { can_add: boolean; @@ -44,7 +49,9 @@ export interface ExlorePageBootstrapData extends JsonObject { common: CommonBootstrapData; } -export default function getInitialState(bootstrapData: ExlorePageBootstrapData) { +export default function getInitialState( + bootstrapData: ExlorePageBootstrapData, +) { const { form_data: rawFormData } = bootstrapData; const { slice } = bootstrapData; const sliceName = slice ? slice.slice_name : null; diff --git a/superset-frontend/src/types/Chart.ts b/superset-frontend/src/types/Chart.ts index a2e9f7dbb516..02b9025c8387 100644 --- a/superset-frontend/src/types/Chart.ts +++ b/superset-frontend/src/types/Chart.ts @@ -46,7 +46,7 @@ export type Slice = { slice_name: string; description: string | null; cache_timeout: number | null; - form_data: QueryFormData; + form_data?: QueryFormData; }; export default Chart; From d01a7b9244da4017aee225ff38ad5be94f6650c9 Mon Sep 17 00:00:00 2001 From: Jesse Yang Date: Thu, 18 Feb 2021 09:18:05 -1000 Subject: [PATCH 03/18] keep provideFormDataToProps to avoid re-render --- superset-frontend/src/explore/components/Control.tsx | 1 - .../src/explore/components/ControlPanelsContainer.tsx | 10 +++++++--- superset-frontend/src/explore/controls.jsx | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/superset-frontend/src/explore/components/Control.tsx b/superset-frontend/src/explore/components/Control.tsx index 6b1e7fa8b885..119023e7bad8 100644 --- a/superset-frontend/src/explore/components/Control.tsx +++ b/superset-frontend/src/explore/components/Control.tsx @@ -35,7 +35,6 @@ export type ControlProps = { tooltipOnClick?: () => ReactNode; places?: number; rightNode?: ReactNode; - controls?: ControlStateMapping; formData?: QueryFormData | null; value?: JsonValue; validationErrors?: any[]; diff --git a/superset-frontend/src/explore/components/ControlPanelsContainer.tsx b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx index 9afd04a3c77d..6cea44e2ff02 100644 --- a/superset-frontend/src/explore/components/ControlPanelsContainer.tsx +++ b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx @@ -159,8 +159,13 @@ class ControlPanelsContainer extends React.Component ); diff --git a/superset-frontend/src/explore/controls.jsx b/superset-frontend/src/explore/controls.jsx index 659da282600b..74e8dcaaf152 100644 --- a/superset-frontend/src/explore/controls.jsx +++ b/superset-frontend/src/explore/controls.jsx @@ -355,6 +355,7 @@ export const controls = { "using the engine's local timezone. Note one can explicitly set the timezone " + 'per the ISO 8601 format if specifying either the start and/or end time.', ), + provideFormDataToProps: true, mapStateToProps: ({ form_data: formData }) => ({ endpoints: formData?.time_range_endpoints, }), @@ -467,6 +468,7 @@ export const controls = { label: t('Filters'), default: null, description: '', + provideFormDataToProps: true, mapStateToProps: state => ({ columns: state.datasource ? state.datasource.columns.filter(c => c.filterable) From 187bcafb77e377a3a7672619b4a29dec0f05cae1 Mon Sep 17 00:00:00 2001 From: Jesse Yang Date: Fri, 19 Feb 2021 09:22:49 -1000 Subject: [PATCH 04/18] Fix lint errors --- superset-frontend/.eslintrc.js | 1 + superset-frontend/src/explore/components/Control.tsx | 2 +- superset-frontend/src/explore/controls.jsx | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js index 0d9531aa951b..5b79778ef525 100644 --- a/superset-frontend/.eslintrc.js +++ b/superset-frontend/.eslintrc.js @@ -104,6 +104,7 @@ module.exports = { 'no-mixed-operators': 0, 'no-multi-assign': 0, 'no-multi-spaces': 0, + 'no-nested-ternary': 0, 'no-prototype-builtins': 0, 'no-restricted-properties': 0, 'no-restricted-imports': [ diff --git a/superset-frontend/src/explore/components/Control.tsx b/superset-frontend/src/explore/components/Control.tsx index 119023e7bad8..f1b6925bd693 100644 --- a/superset-frontend/src/explore/components/Control.tsx +++ b/superset-frontend/src/explore/components/Control.tsx @@ -17,7 +17,7 @@ * under the License. */ import React, { ReactNode } from 'react'; -import { ControlStateMapping, ControlType } from '@superset-ui/chart-controls'; +import { ControlType } from '@superset-ui/chart-controls'; import { JsonValue, QueryFormData } from '@superset-ui/core'; import { ExploreActions } from '../actions/exploreActions'; import controlMap from './controls'; diff --git a/superset-frontend/src/explore/controls.jsx b/superset-frontend/src/explore/controls.jsx index 74e8dcaaf152..ba4378560050 100644 --- a/superset-frontend/src/explore/controls.jsx +++ b/superset-frontend/src/explore/controls.jsx @@ -357,6 +357,7 @@ export const controls = { ), provideFormDataToProps: true, mapStateToProps: ({ form_data: formData }) => ({ + // eslint-disable-next-line camelcase endpoints: formData?.time_range_endpoints, }), }, From dd8f2cc53cc910405287bca31ccadbcc0704f889 Mon Sep 17 00:00:00 2001 From: Jesse Yang Date: Fri, 19 Feb 2021 14:01:39 -1000 Subject: [PATCH 05/18] Fix many typing errors --- .../components/ControlPanelsContainer.tsx | 38 ++++---- .../DateFilterControl/DateFilterControl.tsx | 27 ++---- .../FilterControl/AdhocFilterControl.jsx | 16 +--- .../components/controls/TextControl.tsx | 88 ++++++++----------- superset-frontend/src/explore/controls.jsx | 1 - 5 files changed, 65 insertions(+), 105 deletions(-) diff --git a/superset-frontend/src/explore/components/ControlPanelsContainer.tsx b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx index 6cea44e2ff02..011587785e57 100644 --- a/superset-frontend/src/explore/components/ControlPanelsContainer.tsx +++ b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx @@ -114,21 +114,21 @@ class ControlPanelsContainer extends React.Component { - const { type, default: defaultValue } = control; - if (typeof type === 'string' && defaultValues.includes(type)) { - setControlValue(controlName, defaultValue); - } - }); + Object.entries(this.props.controls).forEach( + ([controlName, controlState]) => { + if ( + // for direct column select controls + controlState.valueKey === 'column_name' || + // for all other controls + 'columns' in controlState + ) { + setControlValue(controlName, controlState.default); + } + }, + ); } } @@ -148,7 +148,7 @@ class ControlPanelsContainer extends React.Component ); diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterControl.tsx b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterControl.tsx index 60b4c501d018..9ccc404e08bf 100644 --- a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterControl.tsx +++ b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterControl.tsx @@ -25,6 +25,7 @@ import { t, TimeRangeEndpoints, } from '@superset-ui/core'; +import { DatasourceMeta } from '@superset-ui/chart-controls'; import { buildTimeRangeString, formatTimeRange, @@ -170,29 +171,21 @@ interface DateFilterControlProps { onChange: (timeRange: string) => void; value?: string; endpoints?: TimeRangeEndpoints; - datasource?: string; - formData?: { datasource: string }; + datasource?: DatasourceMeta; } export default function DateFilterControl(props: DateFilterControlProps) { - const { - value = 'Last week', - endpoints, - onChange, - formData: { datasource } = {}, - } = props; + const { value = 'Last week', endpoints, onChange, datasource } = props; const [actualTimeRange, setActualTimeRange] = useState(value); const [show, setShow] = useState(false); const [frame, setFrame] = useState(guessFrame(value)); - const [isMounted, setIsMounted] = useState(false); const [timeRangeValue, setTimeRangeValue] = useState(value); const [validTimeRange, setValidTimeRange] = useState(false); const [evalResponse, setEvalResponse] = useState(value); const [tooltipTitle, setTooltipTitle] = useState(value); useEffect(() => { - if (!isMounted) setIsMounted(true); fetchTimeRange(value, endpoints).then(({ value: actualRange, error }) => { if (error) { setEvalResponse(error || ''); @@ -227,12 +220,10 @@ export default function DateFilterControl(props: DateFilterControlProps) { }, [value]); useEffect(() => { - if (isMounted) { - onChange('Last week'); - setTimeRangeValue('Last week'); - setFrame(guessFrame('Last week')); - } - }, [datasource]); + onChange('Last week'); + setTimeRangeValue('Last week'); + setFrame(guessFrame('Last week')); + }, [datasource?.id, onChange]); useEffect(() => { fetchTimeRange(timeRangeValue, endpoints).then(({ value, error }) => { @@ -271,7 +262,7 @@ export default function DateFilterControl(props: DateFilterControlProps) { } }; - function onFrame(option: SelectOptionType) { + function onChangeFrame(option: SelectOptionType) { if (option.value === 'No filter') { setTimeRangeValue('No filter'); } @@ -284,7 +275,7 @@ export default function DateFilterControl(props: DateFilterControlProps) {