mirror of
https://github.com/apache/superset.git
synced 2024-09-12 00:29:39 -04:00
fix: Pasting text issues in MetricsControl and AdhocFilterControl inputs (#11445)
* Fix paste not working in Metrics and Filter inputs * Use noOp instead of empty function * Use default Select component instead of OnPasteSelect * Revert onPaste override
This commit is contained in:
parent
ad98981d9d
commit
128ddfabb6
@ -21,7 +21,7 @@ import React from 'react';
|
|||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import OnPasteSelect from 'src/components/Select/OnPasteSelect';
|
import Select from 'src/components/Select';
|
||||||
import AdhocFilter, {
|
import AdhocFilter, {
|
||||||
EXPRESSION_TYPES,
|
EXPRESSION_TYPES,
|
||||||
CLAUSES,
|
CLAUSES,
|
||||||
@ -73,14 +73,14 @@ function setup(overrides) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('AdhocFilterControl', () => {
|
describe('AdhocFilterControl', () => {
|
||||||
it('renders an onPasteSelect', () => {
|
it('renders Select', () => {
|
||||||
const { wrapper } = setup();
|
const { wrapper } = setup();
|
||||||
expect(wrapper.find(OnPasteSelect)).toExist();
|
expect(wrapper.find(Select)).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles saved metrics being selected to filter on', () => {
|
it('handles saved metrics being selected to filter on', () => {
|
||||||
const { wrapper, onChange } = setup({ value: [] });
|
const { wrapper, onChange } = setup({ value: [] });
|
||||||
const select = wrapper.find(OnPasteSelect);
|
const select = wrapper.find(Select);
|
||||||
select.simulate('change', [{ saved_metric_name: 'sum__value' }]);
|
select.simulate('change', [{ saved_metric_name: 'sum__value' }]);
|
||||||
|
|
||||||
const adhocFilter = onChange.lastCall.args[0][0];
|
const adhocFilter = onChange.lastCall.args[0][0];
|
||||||
@ -100,7 +100,7 @@ describe('AdhocFilterControl', () => {
|
|||||||
|
|
||||||
it('handles adhoc metrics being selected to filter on', () => {
|
it('handles adhoc metrics being selected to filter on', () => {
|
||||||
const { wrapper, onChange } = setup({ value: [] });
|
const { wrapper, onChange } = setup({ value: [] });
|
||||||
const select = wrapper.find(OnPasteSelect);
|
const select = wrapper.find(Select);
|
||||||
select.simulate('change', [sumValueAdhocMetric]);
|
select.simulate('change', [sumValueAdhocMetric]);
|
||||||
|
|
||||||
const adhocFilter = onChange.lastCall.args[0][0];
|
const adhocFilter = onChange.lastCall.args[0][0];
|
||||||
@ -120,7 +120,7 @@ describe('AdhocFilterControl', () => {
|
|||||||
|
|
||||||
it('handles columns being selected to filter on', () => {
|
it('handles columns being selected to filter on', () => {
|
||||||
const { wrapper, onChange } = setup({ value: [] });
|
const { wrapper, onChange } = setup({ value: [] });
|
||||||
const select = wrapper.find(OnPasteSelect);
|
const select = wrapper.find(Select);
|
||||||
select.simulate('change', [columns[0]]);
|
select.simulate('change', [columns[0]]);
|
||||||
|
|
||||||
const adhocFilter = onChange.lastCall.args[0][0];
|
const adhocFilter = onChange.lastCall.args[0][0];
|
||||||
@ -140,7 +140,7 @@ describe('AdhocFilterControl', () => {
|
|||||||
|
|
||||||
it('persists existing filters even when new filters are added', () => {
|
it('persists existing filters even when new filters are added', () => {
|
||||||
const { wrapper, onChange } = setup();
|
const { wrapper, onChange } = setup();
|
||||||
const select = wrapper.find(OnPasteSelect);
|
const select = wrapper.find(Select);
|
||||||
select.simulate('change', [simpleAdhocFilter, columns[0]]);
|
select.simulate('change', [simpleAdhocFilter, columns[0]]);
|
||||||
|
|
||||||
const existingAdhocFilter = onChange.lastCall.args[0][0];
|
const existingAdhocFilter = onChange.lastCall.args[0][0];
|
||||||
|
@ -23,7 +23,7 @@ import { shallow } from 'enzyme';
|
|||||||
|
|
||||||
import MetricsControl from 'src/explore/components/controls/MetricsControl';
|
import MetricsControl from 'src/explore/components/controls/MetricsControl';
|
||||||
import { AGGREGATES } from 'src/explore/constants';
|
import { AGGREGATES } from 'src/explore/constants';
|
||||||
import OnPasteSelect from 'src/components/Select/OnPasteSelect';
|
import Select from 'src/components/Select';
|
||||||
import AdhocMetric, { EXPRESSION_TYPES } from 'src/explore/AdhocMetric';
|
import AdhocMetric, { EXPRESSION_TYPES } from 'src/explore/AdhocMetric';
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
@ -63,9 +63,9 @@ const sumValueAdhocMetric = new AdhocMetric({
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('MetricsControl', () => {
|
describe('MetricsControl', () => {
|
||||||
it('renders an OnPasteSelect', () => {
|
it('renders Select', () => {
|
||||||
const { wrapper } = setup();
|
const { wrapper } = setup();
|
||||||
expect(wrapper.find(OnPasteSelect)).toExist();
|
expect(wrapper.find(Select)).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('constructor', () => {
|
describe('constructor', () => {
|
||||||
@ -152,14 +152,14 @@ describe('MetricsControl', () => {
|
|||||||
describe('onChange', () => {
|
describe('onChange', () => {
|
||||||
it('handles saved metrics being selected', () => {
|
it('handles saved metrics being selected', () => {
|
||||||
const { wrapper, onChange } = setup();
|
const { wrapper, onChange } = setup();
|
||||||
const select = wrapper.find(OnPasteSelect);
|
const select = wrapper.find(Select);
|
||||||
select.simulate('change', [{ metric_name: 'sum__value' }]);
|
select.simulate('change', [{ metric_name: 'sum__value' }]);
|
||||||
expect(onChange.lastCall.args).toEqual([['sum__value']]);
|
expect(onChange.lastCall.args).toEqual([['sum__value']]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles columns being selected', () => {
|
it('handles columns being selected', () => {
|
||||||
const { wrapper, onChange } = setup();
|
const { wrapper, onChange } = setup();
|
||||||
const select = wrapper.find(OnPasteSelect);
|
const select = wrapper.find(Select);
|
||||||
select.simulate('change', [valueColumn]);
|
select.simulate('change', [valueColumn]);
|
||||||
|
|
||||||
const adhocMetric = onChange.lastCall.args[0][0];
|
const adhocMetric = onChange.lastCall.args[0][0];
|
||||||
@ -184,7 +184,7 @@ describe('MetricsControl', () => {
|
|||||||
it('handles aggregates being selected', () => {
|
it('handles aggregates being selected', () => {
|
||||||
return new Promise(done => {
|
return new Promise(done => {
|
||||||
const { wrapper, onChange } = setup();
|
const { wrapper, onChange } = setup();
|
||||||
const select = wrapper.find(OnPasteSelect);
|
const select = wrapper.find(Select);
|
||||||
|
|
||||||
// mock out the Select ref
|
// mock out the Select ref
|
||||||
const instance = wrapper.instance();
|
const instance = wrapper.instance();
|
||||||
@ -220,7 +220,7 @@ describe('MetricsControl', () => {
|
|||||||
|
|
||||||
it('preserves existing selected AdhocMetrics', () => {
|
it('preserves existing selected AdhocMetrics', () => {
|
||||||
const { wrapper, onChange } = setup();
|
const { wrapper, onChange } = setup();
|
||||||
const select = wrapper.find(OnPasteSelect);
|
const select = wrapper.find(Select);
|
||||||
select.simulate('change', [
|
select.simulate('change', [
|
||||||
{ metric_name: 'sum__value' },
|
{ metric_name: 'sum__value' },
|
||||||
sumValueAdhocMetric,
|
sumValueAdhocMetric,
|
||||||
@ -262,6 +262,18 @@ describe('MetricsControl', () => {
|
|||||||
wrapper.instance().checkIfAggregateInInput('colu');
|
wrapper.instance().checkIfAggregateInInput('colu');
|
||||||
expect(wrapper.state('aggregateInInput')).toBeNull();
|
expect(wrapper.state('aggregateInInput')).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles an aggregate in the input when paste event fires', () => {
|
||||||
|
const { wrapper } = setup();
|
||||||
|
expect(wrapper.state('aggregateInInput')).toBeNull();
|
||||||
|
|
||||||
|
const mEvent = {
|
||||||
|
clipboardData: { getData: jest.fn().mockReturnValueOnce('AVG(') },
|
||||||
|
};
|
||||||
|
const select = wrapper.find(Select);
|
||||||
|
select.simulate('paste', mEvent);
|
||||||
|
expect(wrapper.state('aggregateInInput')).toBe(AGGREGATES.AVG);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('option filter', () => {
|
describe('option filter', () => {
|
||||||
|
@ -21,8 +21,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
import { t, logging, SupersetClient } from '@superset-ui/core';
|
import { t, logging, SupersetClient } from '@superset-ui/core';
|
||||||
|
|
||||||
import OnPasteSelect from 'src/components/Select/OnPasteSelect';
|
import Select from 'src/components/Select';
|
||||||
|
|
||||||
import ControlHeader from '../ControlHeader';
|
import ControlHeader from '../ControlHeader';
|
||||||
import adhocFilterType from '../../propTypes/adhocFilterType';
|
import adhocFilterType from '../../propTypes/adhocFilterType';
|
||||||
import adhocMetricType from '../../propTypes/adhocMetricType';
|
import adhocMetricType from '../../propTypes/adhocMetricType';
|
||||||
@ -267,7 +266,7 @@ export default class AdhocFilterControl extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="metrics-select" data-test="adhoc-filter-control">
|
<div className="metrics-select" data-test="adhoc-filter-control">
|
||||||
<ControlHeader {...this.props} />
|
<ControlHeader {...this.props} />
|
||||||
<OnPasteSelect
|
<Select
|
||||||
isMulti
|
isMulti
|
||||||
isLoading={this.props.isLoading}
|
isLoading={this.props.isLoading}
|
||||||
name={`select-${this.props.name}`}
|
name={`select-${this.props.name}`}
|
||||||
|
@ -21,8 +21,7 @@ import PropTypes from 'prop-types';
|
|||||||
import { t } from '@superset-ui/core';
|
import { t } from '@superset-ui/core';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
|
|
||||||
import OnPasteSelect from 'src/components/Select/OnPasteSelect';
|
import Select from 'src/components/Select';
|
||||||
|
|
||||||
import ControlHeader from '../ControlHeader';
|
import ControlHeader from '../ControlHeader';
|
||||||
import MetricDefinitionOption from '../MetricDefinitionOption';
|
import MetricDefinitionOption from '../MetricDefinitionOption';
|
||||||
import MetricDefinitionValue from '../MetricDefinitionValue';
|
import MetricDefinitionValue from '../MetricDefinitionValue';
|
||||||
@ -143,6 +142,7 @@ export default class MetricsControl extends React.PureComponent {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.onChange = this.onChange.bind(this);
|
this.onChange = this.onChange.bind(this);
|
||||||
|
this.onPaste = this.onPaste.bind(this);
|
||||||
this.onMetricEdit = this.onMetricEdit.bind(this);
|
this.onMetricEdit = this.onMetricEdit.bind(this);
|
||||||
this.checkIfAggregateInInput = this.checkIfAggregateInInput.bind(this);
|
this.checkIfAggregateInInput = this.checkIfAggregateInInput.bind(this);
|
||||||
this.optionsForSelect = this.optionsForSelect.bind(this);
|
this.optionsForSelect = this.optionsForSelect.bind(this);
|
||||||
@ -258,6 +258,14 @@ export default class MetricsControl extends React.PureComponent {
|
|||||||
this.props.onChange(this.props.multi ? optionValues : optionValues[0]);
|
this.props.onChange(this.props.multi ? optionValues : optionValues[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onPaste(evt) {
|
||||||
|
const clipboard = evt.clipboardData.getData('Text');
|
||||||
|
if (!clipboard) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.checkIfAggregateInInput(clipboard);
|
||||||
|
}
|
||||||
|
|
||||||
checkIfAggregateInInput(input) {
|
checkIfAggregateInInput(input) {
|
||||||
const lowercaseInput = input.toLowerCase();
|
const lowercaseInput = input.toLowerCase();
|
||||||
const aggregateInInput =
|
const aggregateInInput =
|
||||||
@ -335,7 +343,7 @@ export default class MetricsControl extends React.PureComponent {
|
|||||||
return (
|
return (
|
||||||
<div className="metrics-select">
|
<div className="metrics-select">
|
||||||
<ControlHeader {...this.props} />
|
<ControlHeader {...this.props} />
|
||||||
<OnPasteSelect
|
<Select
|
||||||
isLoading={this.props.isLoading}
|
isLoading={this.props.isLoading}
|
||||||
isMulti={this.props.multi}
|
isMulti={this.props.multi}
|
||||||
name={`select-${this.props.name}`}
|
name={`select-${this.props.name}`}
|
||||||
@ -344,6 +352,7 @@ export default class MetricsControl extends React.PureComponent {
|
|||||||
value={this.state.value}
|
value={this.state.value}
|
||||||
labelKey="label"
|
labelKey="label"
|
||||||
valueKey="optionName"
|
valueKey="optionName"
|
||||||
|
onPaste={this.onPaste}
|
||||||
clearable={this.props.clearable}
|
clearable={this.props.clearable}
|
||||||
closeOnSelect
|
closeOnSelect
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
|
Loading…
Reference in New Issue
Block a user