未验证 提交 4d179622 编写于 作者: J Jesse Yang 提交者: GitHub

fix(explore): edit datasource does not update control states (#10284)

上级 4e4ccd48
...@@ -21,11 +21,60 @@ ...@@ -21,11 +21,60 @@
// *********************************************** // ***********************************************
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './visualizations/shared.helper'; import { FORM_DATA_DEFAULTS, NUM_METRIC } from './visualizations/shared.helper';
describe('Groupby', () => { describe('Datasource control', () => {
it('Set groupby', () => { const newMetricName = `abc${Date.now()}`;
before(() => {
cy.server(); cy.server();
cy.login(); cy.login();
cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson');
});
it('should allow edit datasource', () => {
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@postJson' });
cy.get('#datasource_menu').click();
cy.get('a').contains('Edit Datasource').click();
// create new metric
cy.get('button').contains('Add Item').click();
cy.get('input[value="<new metric>"]').click();
cy.get('input[value="<new metric>"]')
.focus()
.clear()
.type(`${newMetricName}{enter}`);
cy.get('.modal-footer button').contains('Save').click();
cy.get('.modal-footer button').contains('OK').click();
// select new metric
cy.get('.metrics-select:eq(0)').click();
cy.get('.metrics-select:eq(0) input[type="text"]')
.focus()
.type(newMetricName);
cy.get('.metrics-select:eq(0) .Select__menu .Select__option')
.contains(newMetricName)
.click();
cy.get('.metrics-select:eq(0) .Select__multi-value__label')
.contains(newMetricName)
.click();
// delete metric
cy.get('#datasource_menu').click();
cy.get('a').contains('Edit Datasource').click();
cy.get(`input[value="${newMetricName}"]`)
.closest('tr')
.find('.fa-close')
.click();
cy.get('.modal-footer button').contains('Save').click();
cy.get('.modal-footer button').contains('OK').click();
cy.get('.Select__multi-value__label')
.contains(newMetricName)
.should('not.exist');
});
});
describe('Groupby control', () => {
it('Set groupby', () => {
cy.server();
cy.login();
cy.route('GET', '/superset/explore_json/**').as('getJson'); cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson'); cy.route('POST', '/superset/explore_json/**').as('postJson');
cy.visitChartByName('Num Births Trend'); cy.visitChartByName('Num Births Trend');
...@@ -71,5 +120,7 @@ describe('Time range filter', () => { ...@@ -71,5 +120,7 @@ describe('Time range filter', () => {
}); });
}); });
}); });
cy.get('#filter-popover button').contains('Ok').click();
cy.get('#filter-popover').should('not.exist');
}); });
}); });
...@@ -41,6 +41,9 @@ const defaultProps = { ...@@ -41,6 +41,9 @@ const defaultProps = {
name: 'main', name: 'main',
}, },
}, },
actions: {
setDatasource: sinon.spy(),
},
onChange: sinon.spy(), onChange: sinon.spy(),
}; };
...@@ -71,15 +74,15 @@ describe('DatasourceControl', () => { ...@@ -71,15 +74,15 @@ describe('DatasourceControl', () => {
let wrapper = setup(); let wrapper = setup();
expect(wrapper.find('#datasource_menu')).toHaveLength(1); expect(wrapper.find('#datasource_menu')).toHaveLength(1);
expect(wrapper.find('#datasource_menu').dive().find(MenuItem)).toHaveLength( expect(wrapper.find('#datasource_menu').dive().find(MenuItem)).toHaveLength(
2, 3,
); );
wrapper = setup({ wrapper = setup({
onDatasourceSave: () => {}, isEditable: false,
}); });
expect(wrapper.find('#datasource_menu')).toHaveLength(1); expect(wrapper.find('#datasource_menu')).toHaveLength(1);
expect(wrapper.find('#datasource_menu').dive().find(MenuItem)).toHaveLength( expect(wrapper.find('#datasource_menu').dive().find(MenuItem)).toHaveLength(
3, 2,
); );
}); });
}); });
...@@ -27,7 +27,6 @@ import { ...@@ -27,7 +27,6 @@ import {
getFormDataFromControls, getFormDataFromControls,
applyMapStateToPropsToControl, applyMapStateToPropsToControl,
getAllControlsState, getAllControlsState,
getControlsState,
} from 'src/explore/controlUtils'; } from 'src/explore/controlUtils';
describe('controlUtils', () => { describe('controlUtils', () => {
......
...@@ -26,6 +26,10 @@ const propTypes = { ...@@ -26,6 +26,10 @@ const propTypes = {
tooltip: PropTypes.node.isRequired, tooltip: PropTypes.node.isRequired,
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
placement: PropTypes.string, placement: PropTypes.string,
trigger: PropTypes.oneOfType([
PropTypes.string,
PropTypes.arrayOf(PropTypes.string),
]),
}; };
const defaultProps = { const defaultProps = {
...@@ -37,11 +41,13 @@ export default function TooltipWrapper({ ...@@ -37,11 +41,13 @@ export default function TooltipWrapper({
tooltip, tooltip,
children, children,
placement, placement,
trigger,
}) { }) {
return ( return (
<OverlayTrigger <OverlayTrigger
placement={placement} placement={placement}
overlay={<Tooltip id={`${kebabCase(label)}-tooltip`}>{tooltip}</Tooltip>} overlay={<Tooltip id={`${kebabCase(label)}-tooltip`}>{tooltip}</Tooltip>}
trigger={trigger}
> >
{children} {children}
</OverlayTrigger> </OverlayTrigger>
......
...@@ -389,6 +389,7 @@ function mapStateToProps(state) { ...@@ -389,6 +389,7 @@ function mapStateToProps(state) {
const form_data = getFormDataFromControls(explore.controls); const form_data = getFormDataFromControls(explore.controls);
const chartKey = Object.keys(charts)[0]; const chartKey = Object.keys(charts)[0];
const chart = charts[chartKey]; const chart = charts[chartKey];
return { return {
isDatasourceMetaLoading: explore.isDatasourceMetaLoading, isDatasourceMetaLoading: explore.isDatasourceMetaLoading,
datasource: explore.datasource, datasource: explore.datasource,
......
...@@ -38,9 +38,11 @@ import TooltipWrapper from '../../../components/TooltipWrapper'; ...@@ -38,9 +38,11 @@ import TooltipWrapper from '../../../components/TooltipWrapper';
import './DatasourceControl.less'; import './DatasourceControl.less';
const propTypes = { const propTypes = {
actions: PropTypes.object.isRequired,
onChange: PropTypes.func, onChange: PropTypes.func,
value: PropTypes.string, value: PropTypes.string,
datasource: PropTypes.object.isRequired, datasource: PropTypes.object.isRequired,
isEditable: PropTypes.bool,
onDatasourceSave: PropTypes.func, onDatasourceSave: PropTypes.func,
}; };
...@@ -48,6 +50,7 @@ const defaultProps = { ...@@ -48,6 +50,7 @@ const defaultProps = {
onChange: () => {}, onChange: () => {},
onDatasourceSave: null, onDatasourceSave: null,
value: null, value: null,
isEditable: true,
}; };
class DatasourceControl extends React.PureComponent { class DatasourceControl extends React.PureComponent {
...@@ -58,6 +61,7 @@ class DatasourceControl extends React.PureComponent { ...@@ -58,6 +61,7 @@ class DatasourceControl extends React.PureComponent {
showChangeDatasourceModal: false, showChangeDatasourceModal: false,
menuExpanded: false, menuExpanded: false,
}; };
this.onDatasourceSave = this.onDatasourceSave.bind(this);
this.toggleChangeDatasourceModal = this.toggleChangeDatasourceModal.bind( this.toggleChangeDatasourceModal = this.toggleChangeDatasourceModal.bind(
this, this,
); );
...@@ -66,6 +70,13 @@ class DatasourceControl extends React.PureComponent { ...@@ -66,6 +70,13 @@ class DatasourceControl extends React.PureComponent {
this.renderDatasource = this.renderDatasource.bind(this); this.renderDatasource = this.renderDatasource.bind(this);
} }
onDatasourceSave(datasource) {
this.props.actions.setDatasource(datasource);
if (this.props.onDatasourceSave) {
this.props.onDatasourceSave(datasource);
}
}
toggleShowDatasource() { toggleShowDatasource() {
this.setState(({ showDatasource }) => ({ this.setState(({ showDatasource }) => ({
showDatasource: !showDatasource, showDatasource: !showDatasource,
...@@ -120,7 +131,7 @@ class DatasourceControl extends React.PureComponent { ...@@ -120,7 +131,7 @@ class DatasourceControl extends React.PureComponent {
render() { render() {
const { showChangeDatasourceModal, showEditDatasourceModal } = this.state; const { showChangeDatasourceModal, showEditDatasourceModal } = this.state;
const { datasource, onChange, onDatasourceSave, value } = this.props; const { datasource, onChange, value } = this.props;
return ( return (
<div> <div>
<ControlHeader {...this.props} /> <ControlHeader {...this.props} />
...@@ -128,6 +139,7 @@ class DatasourceControl extends React.PureComponent { ...@@ -128,6 +139,7 @@ class DatasourceControl extends React.PureComponent {
<TooltipWrapper <TooltipWrapper
label="change-datasource" label="change-datasource"
tooltip={t('Click to change the datasource')} tooltip={t('Click to change the datasource')}
trigger={['hover']}
> >
<DropdownButton <DropdownButton
title={datasource.name} title={datasource.name}
...@@ -148,7 +160,7 @@ class DatasourceControl extends React.PureComponent { ...@@ -148,7 +160,7 @@ class DatasourceControl extends React.PureComponent {
{t('Explore in SQL Lab')} {t('Explore in SQL Lab')}
</MenuItem> </MenuItem>
)} )}
{!!this.props.onDatasourceSave && ( {this.props.isEditable && (
<MenuItem eventKey="3" onClick={this.toggleEditDatasourceModal}> <MenuItem eventKey="3" onClick={this.toggleEditDatasourceModal}>
{t('Edit Datasource')} {t('Edit Datasource')}
</MenuItem> </MenuItem>
...@@ -179,11 +191,11 @@ class DatasourceControl extends React.PureComponent { ...@@ -179,11 +191,11 @@ class DatasourceControl extends React.PureComponent {
<DatasourceModal <DatasourceModal
datasource={datasource} datasource={datasource}
show={showEditDatasourceModal} show={showEditDatasourceModal}
onDatasourceSave={onDatasourceSave} onDatasourceSave={this.onDatasourceSave}
onHide={this.toggleEditDatasourceModal} onHide={this.toggleEditDatasourceModal}
/> />
<ChangeDatasourceModal <ChangeDatasourceModal
onDatasourceSave={onDatasourceSave} onDatasourceSave={this.onDatasourceSave}
onHide={this.toggleChangeDatasourceModal} onHide={this.toggleChangeDatasourceModal}
show={showChangeDatasourceModal} show={showChangeDatasourceModal}
onChange={onChange} onChange={onChange}
......
...@@ -20,7 +20,6 @@ import memoizeOne from 'memoize-one'; ...@@ -20,7 +20,6 @@ import memoizeOne from 'memoize-one';
import { getChartControlPanelRegistry } from '@superset-ui/chart'; import { getChartControlPanelRegistry } from '@superset-ui/chart';
import { expandControlConfig } from '@superset-ui/chart-controls'; import { expandControlConfig } from '@superset-ui/chart-controls';
import { controls as SHARED_CONTROLS } from './controls'; import { controls as SHARED_CONTROLS } from './controls';
import * as exploreActions from './actions/exploreActions';
import * as SECTIONS from './controlPanels/sections'; import * as SECTIONS from './controlPanels/sections';
export function getFormDataFromControls(controlsState) { export function getFormDataFromControls(controlsState) {
...@@ -94,7 +93,7 @@ export function applyMapStateToPropsToControl(controlState, controlPanelState) { ...@@ -94,7 +93,7 @@ export function applyMapStateToPropsToControl(controlState, controlPanelState) {
if (mapStateToProps && controlPanelState) { if (mapStateToProps && controlPanelState) {
return { return {
...controlState, ...controlState,
...mapStateToProps(controlPanelState, controlState, exploreActions), ...mapStateToProps(controlPanelState, controlState),
}; };
} }
return controlState; return controlState;
......
...@@ -204,9 +204,9 @@ export const controls = { ...@@ -204,9 +204,9 @@ export const controls = {
label: t('Datasource'), label: t('Datasource'),
default: null, default: null,
description: null, description: null,
mapStateToProps: (state, control, actions) => ({ mapStateToProps: ({ datasource }) => ({
datasource: state.datasource, datasource,
onDatasourceSave: actions ? actions.setDatasource : () => {}, isEditable: !!datasource,
}), }),
}, },
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册