mirror of
https://github.com/apache/superset.git
synced 2024-09-16 02:29:39 -04:00
feat(explore): collapse time section if no ts columns (#14493)
* feat(explore): collapse time section if no ts columns * fix viz change bug * fix test
This commit is contained in:
parent
05c24056b5
commit
680c96ec54
@ -111,7 +111,7 @@ describe('VizType control', () => {
|
|||||||
// should load mathjs for line chart
|
// should load mathjs for line chart
|
||||||
cy.get('script[src*="mathjs"]').should('have.length', 1);
|
cy.get('script[src*="mathjs"]').should('have.length', 1);
|
||||||
cy.get('script').then(nodes => {
|
cy.get('script').then(nodes => {
|
||||||
expect(nodes.length).to.eq(numScripts);
|
expect(nodes.length).to.greaterThan(numScripts);
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.get('button[data-test="run-query-button"]').click();
|
cy.get('button[data-test="run-query-button"]').click();
|
||||||
|
@ -21,6 +21,7 @@ import React from 'react';
|
|||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
|
ensureIsArray,
|
||||||
t,
|
t,
|
||||||
styled,
|
styled,
|
||||||
getChartControlPanelRegistry,
|
getChartControlPanelRegistry,
|
||||||
@ -31,8 +32,10 @@ import {
|
|||||||
ControlPanelSectionConfig,
|
ControlPanelSectionConfig,
|
||||||
ControlState,
|
ControlState,
|
||||||
CustomControlItem,
|
CustomControlItem,
|
||||||
|
DatasourceMeta,
|
||||||
ExpandedControlItem,
|
ExpandedControlItem,
|
||||||
InfoTooltipWithTrigger,
|
InfoTooltipWithTrigger,
|
||||||
|
sections,
|
||||||
} from '@superset-ui/chart-controls';
|
} from '@superset-ui/chart-controls';
|
||||||
|
|
||||||
import Collapse from 'src/components/Collapse';
|
import Collapse from 'src/components/Collapse';
|
||||||
@ -102,29 +105,129 @@ const ControlPanelsTabs = styled(Tabs)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export class ControlPanelsContainer extends React.Component<ControlPanelsContainerProps> {
|
type ControlPanelsContainerState = {
|
||||||
|
expandedQuerySections: string[];
|
||||||
|
expandedCustomizeSections: string[];
|
||||||
|
querySections: ControlPanelSectionConfig[];
|
||||||
|
customizeSections: ControlPanelSectionConfig[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const isTimeSection = (section: ControlPanelSectionConfig): boolean =>
|
||||||
|
!!section.label &&
|
||||||
|
(sections.legacyRegularTime.label === section.label ||
|
||||||
|
sections.legacyTimeseriesTime.label === section.label);
|
||||||
|
|
||||||
|
const hasTimeColumn = (datasource: DatasourceMeta): boolean =>
|
||||||
|
datasource?.columns?.some(c => c.is_dttm) ||
|
||||||
|
datasource.type === DatasourceType.Druid;
|
||||||
|
|
||||||
|
const sectionsToExpand = (
|
||||||
|
sections: ControlPanelSectionConfig[],
|
||||||
|
datasource: DatasourceMeta,
|
||||||
|
): string[] =>
|
||||||
|
// avoid expanding time section if datasource doesn't include time column
|
||||||
|
sections.reduce(
|
||||||
|
(acc, section) =>
|
||||||
|
section.expanded && (!isTimeSection(section) || hasTimeColumn(datasource))
|
||||||
|
? [...acc, String(section.label)]
|
||||||
|
: acc,
|
||||||
|
[] as string[],
|
||||||
|
);
|
||||||
|
|
||||||
|
function getState(
|
||||||
|
props: ControlPanelsContainerProps,
|
||||||
|
): ControlPanelsContainerState {
|
||||||
|
const {
|
||||||
|
exploreState: { datasource },
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const querySections: ControlPanelSectionConfig[] = [];
|
||||||
|
const customizeSections: ControlPanelSectionConfig[] = [];
|
||||||
|
|
||||||
|
getSectionsToRender(props.form_data.viz_type, props.datasource_type).forEach(
|
||||||
|
section => {
|
||||||
|
// if at least one control in the section is not `renderTrigger`
|
||||||
|
// or asks to be displayed at the Data tab
|
||||||
|
if (
|
||||||
|
section.tabOverride === 'data' ||
|
||||||
|
section.controlSetRows.some(rows =>
|
||||||
|
rows.some(
|
||||||
|
control =>
|
||||||
|
control &&
|
||||||
|
typeof control === 'object' &&
|
||||||
|
'config' in control &&
|
||||||
|
control.config &&
|
||||||
|
(!control.config.renderTrigger ||
|
||||||
|
control.config.tabOverride === 'data'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
querySections.push(section);
|
||||||
|
} else {
|
||||||
|
customizeSections.push(section);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const expandedQuerySections: string[] = sectionsToExpand(
|
||||||
|
querySections,
|
||||||
|
datasource,
|
||||||
|
);
|
||||||
|
const expandedCustomizeSections: string[] = sectionsToExpand(
|
||||||
|
customizeSections,
|
||||||
|
datasource,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
expandedQuerySections,
|
||||||
|
expandedCustomizeSections,
|
||||||
|
querySections,
|
||||||
|
customizeSections,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ControlPanelsContainer extends React.Component<
|
||||||
|
ControlPanelsContainerProps,
|
||||||
|
ControlPanelsContainerState
|
||||||
|
> {
|
||||||
// trigger updates to the component when async plugins load
|
// trigger updates to the component when async plugins load
|
||||||
static contextType = PluginContext;
|
static contextType = PluginContext;
|
||||||
|
|
||||||
constructor(props: ControlPanelsContainerProps) {
|
constructor(props: ControlPanelsContainerProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
expandedQuerySections: [],
|
||||||
|
expandedCustomizeSections: [],
|
||||||
|
querySections: [],
|
||||||
|
customizeSections: [],
|
||||||
|
};
|
||||||
this.renderControl = this.renderControl.bind(this);
|
this.renderControl = this.renderControl.bind(this);
|
||||||
this.renderControlPanelSection = this.renderControlPanelSection.bind(this);
|
this.renderControlPanelSection = this.renderControlPanelSection.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
sectionsToRender(): ExpandedControlPanelSectionConfig[] {
|
static getDerivedStateFromProps(
|
||||||
return getSectionsToRender(
|
props: ControlPanelsContainerProps,
|
||||||
this.props.form_data.viz_type,
|
state: ControlPanelsContainerState,
|
||||||
this.props.datasource_type,
|
): ControlPanelsContainerState {
|
||||||
);
|
// only update the sections, not the expanded/collapsed state
|
||||||
|
const newState = getState(props);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
customizeSections: newState.customizeSections,
|
||||||
|
querySections: newState.querySections,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
sectionsToExpand(sections: ControlPanelSectionConfig[]) {
|
componentDidUpdate(prevProps: ControlPanelsContainerProps) {
|
||||||
return sections.reduce(
|
if (
|
||||||
(acc, section) =>
|
this.props.form_data.datasource !== prevProps.form_data.datasource ||
|
||||||
section.expanded ? [...acc, String(section.label)] : acc,
|
this.props.form_data.viz_type !== prevProps.form_data.viz_type
|
||||||
[] as string[],
|
) {
|
||||||
);
|
// eslint-disable-next-line react/no-did-update-set-state
|
||||||
|
this.setState(getState(this.props));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setState(getState(this.props));
|
||||||
}
|
}
|
||||||
|
|
||||||
renderControl({ name, config }: CustomControlItem) {
|
renderControl({ name, config }: CustomControlItem) {
|
||||||
@ -260,36 +363,7 @@ export class ControlPanelsContainer extends React.Component<ControlPanelsContain
|
|||||||
return <Loading />;
|
return <Loading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const querySectionsToRender: ExpandedControlPanelSectionConfig[] = [];
|
const showCustomizeTab = this.state.customizeSections.length > 0;
|
||||||
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
|
|
||||||
if (
|
|
||||||
section.tabOverride === 'data' ||
|
|
||||||
section.controlSetRows.some(rows =>
|
|
||||||
rows.some(
|
|
||||||
control =>
|
|
||||||
control &&
|
|
||||||
typeof control === 'object' &&
|
|
||||||
'config' in control &&
|
|
||||||
control.config &&
|
|
||||||
(!control.config.renderTrigger ||
|
|
||||||
control.config.tabOverride === 'data'),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
querySectionsToRender.push(section);
|
|
||||||
} else {
|
|
||||||
displaySectionsToRender.push(section);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const showCustomizeTab = displaySectionsToRender.length > 0;
|
|
||||||
const expandedQuerySections = this.sectionsToExpand(querySectionsToRender);
|
|
||||||
const expandedCustomSections = this.sectionsToExpand(
|
|
||||||
displaySectionsToRender,
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<Styles>
|
<Styles>
|
||||||
<ControlPanelsTabs
|
<ControlPanelsTabs
|
||||||
@ -300,22 +374,34 @@ export class ControlPanelsContainer extends React.Component<ControlPanelsContain
|
|||||||
<Tabs.TabPane key="query" tab={t('Data')}>
|
<Tabs.TabPane key="query" tab={t('Data')}>
|
||||||
<Collapse
|
<Collapse
|
||||||
bordered
|
bordered
|
||||||
defaultActiveKey={expandedQuerySections}
|
activeKey={this.state.expandedQuerySections}
|
||||||
expandIconPosition="right"
|
expandIconPosition="right"
|
||||||
|
onChange={selection => {
|
||||||
|
this.setState({
|
||||||
|
expandedQuerySections: ensureIsArray(selection),
|
||||||
|
});
|
||||||
|
}}
|
||||||
ghost
|
ghost
|
||||||
>
|
>
|
||||||
{querySectionsToRender.map(this.renderControlPanelSection)}
|
{this.state.querySections.map(this.renderControlPanelSection)}
|
||||||
</Collapse>
|
</Collapse>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
{showCustomizeTab && (
|
{showCustomizeTab && (
|
||||||
<Tabs.TabPane key="display" tab={t('Customize')}>
|
<Tabs.TabPane key="display" tab={t('Customize')}>
|
||||||
<Collapse
|
<Collapse
|
||||||
bordered
|
bordered
|
||||||
defaultActiveKey={expandedCustomSections}
|
activeKey={this.state.expandedCustomizeSections}
|
||||||
expandIconPosition="right"
|
expandIconPosition="right"
|
||||||
|
onChange={selection => {
|
||||||
|
this.setState({
|
||||||
|
expandedCustomizeSections: ensureIsArray(selection),
|
||||||
|
});
|
||||||
|
}}
|
||||||
ghost
|
ghost
|
||||||
>
|
>
|
||||||
{displaySectionsToRender.map(this.renderControlPanelSection)}
|
{this.state.customizeSections.map(
|
||||||
|
this.renderControlPanelSection,
|
||||||
|
)}
|
||||||
</Collapse>
|
</Collapse>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
)}
|
)}
|
||||||
|
Loading…
Reference in New Issue
Block a user