mirror of
https://github.com/apache/superset.git
synced 2024-09-12 00:29:39 -04:00
fix: Issues with filters and metrics popovers (#11578)
* Fix bugs in AdhocFilterEditPopover * Fix bugs in AdhocMetricEditPopover * Remove handleMultiComparatorInputHeightChange function * Fix tests
This commit is contained in:
parent
1490f3074d
commit
6d5d92a6fe
@ -199,16 +199,4 @@ describe('AdhocFilterEditPopoverSimpleTabContent', () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('expands when its multi comparator input field expands', () => {
|
|
||||||
const { wrapper, onHeightChange } = setup();
|
|
||||||
|
|
||||||
wrapper.instance().multiComparatorComponent = {
|
|
||||||
select: { select: { controlRef: { clientHeight: 57 } } },
|
|
||||||
};
|
|
||||||
wrapper.instance().handleMultiComparatorInputHeightChange();
|
|
||||||
|
|
||||||
expect(onHeightChange.calledOnce).toBe(true);
|
|
||||||
expect(onHeightChange.lastCall.args[0]).toBe(27);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -126,9 +126,9 @@ describe('AdhocFilterEditPopover', () => {
|
|||||||
wrapper.instance().onDragDown = sinon.spy();
|
wrapper.instance().onDragDown = sinon.spy();
|
||||||
wrapper.instance().forceUpdate();
|
wrapper.instance().forceUpdate();
|
||||||
|
|
||||||
expect(wrapper.find('i.fa-expand')).toExist();
|
expect(wrapper.find('.fa-expand')).toExist();
|
||||||
expect(wrapper.instance().onDragDown.calledOnce).toBe(false);
|
expect(wrapper.instance().onDragDown.calledOnce).toBe(false);
|
||||||
wrapper.find('i.fa-expand').simulate('mouseDown', {});
|
wrapper.find('.fa-expand').simulate('mouseDown', {});
|
||||||
expect(wrapper.instance().onDragDown.calledOnce).toBe(true);
|
expect(wrapper.instance().onDragDown.calledOnce).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -113,9 +113,9 @@ describe('AdhocMetricEditPopover', () => {
|
|||||||
wrapper.instance().onDragDown = sinon.spy();
|
wrapper.instance().onDragDown = sinon.spy();
|
||||||
wrapper.instance().forceUpdate();
|
wrapper.instance().forceUpdate();
|
||||||
|
|
||||||
expect(wrapper.find('i.fa-expand')).toExist();
|
expect(wrapper.find('.fa-expand')).toExist();
|
||||||
expect(wrapper.instance().onDragDown.calledOnce).toBe(false);
|
expect(wrapper.instance().onDragDown.calledOnce).toBe(false);
|
||||||
wrapper.find('i.fa-expand').simulate('mouseDown');
|
wrapper.find('.fa-expand').simulate('mouseDown');
|
||||||
expect(wrapper.instance().onDragDown.calledOnce).toBe(true);
|
expect(wrapper.instance().onDragDown.calledOnce).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Button from 'src/components/Button';
|
import Button from 'src/components/Button';
|
||||||
import { t } from '@superset-ui/core';
|
import { styled, t } from '@superset-ui/core';
|
||||||
|
|
||||||
import Tabs from 'src/common/components/Tabs';
|
import Tabs from 'src/common/components/Tabs';
|
||||||
import columnType from '../propTypes/columnType';
|
import columnType from '../propTypes/columnType';
|
||||||
@ -45,7 +45,11 @@ const propTypes = {
|
|||||||
theme: PropTypes.object,
|
theme: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
const startingWidth = 300;
|
const ResizeIcon = styled.i`
|
||||||
|
margin-left: ${({ theme }) => theme.gridUnit * 2}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const startingWidth = 320;
|
||||||
const startingHeight = 240;
|
const startingHeight = 240;
|
||||||
|
|
||||||
export default class AdhocFilterEditPopover extends React.Component {
|
export default class AdhocFilterEditPopover extends React.Component {
|
||||||
@ -63,6 +67,8 @@ export default class AdhocFilterEditPopover extends React.Component {
|
|||||||
width: startingWidth,
|
width: startingWidth,
|
||||||
height: startingHeight,
|
height: startingHeight,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.popoverContentRef = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -136,6 +142,7 @@ export default class AdhocFilterEditPopover extends React.Component {
|
|||||||
id="filter-edit-popover"
|
id="filter-edit-popover"
|
||||||
{...popoverProps}
|
{...popoverProps}
|
||||||
data-test="filter-edit-popover"
|
data-test="filter-edit-popover"
|
||||||
|
ref={this.popoverContentRef}
|
||||||
>
|
>
|
||||||
<Tabs
|
<Tabs
|
||||||
id="adhoc-filter-edit-tabs"
|
id="adhoc-filter-edit-tabs"
|
||||||
@ -156,6 +163,7 @@ export default class AdhocFilterEditPopover extends React.Component {
|
|||||||
datasource={datasource}
|
datasource={datasource}
|
||||||
onHeightChange={this.adjustHeight}
|
onHeightChange={this.adjustHeight}
|
||||||
partitionColumn={partitionColumn}
|
partitionColumn={partitionColumn}
|
||||||
|
popoverRef={this.popoverContentRef}
|
||||||
/>
|
/>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane
|
<Tabs.TabPane
|
||||||
@ -195,7 +203,7 @@ export default class AdhocFilterEditPopover extends React.Component {
|
|||||||
>
|
>
|
||||||
{t('Save')}
|
{t('Save')}
|
||||||
</Button>
|
</Button>
|
||||||
<i
|
<ResizeIcon
|
||||||
role="button"
|
role="button"
|
||||||
aria-label="Resize"
|
aria-label="Resize"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
@ -51,6 +51,7 @@ const propTypes = {
|
|||||||
onHeightChange: PropTypes.func.isRequired,
|
onHeightChange: PropTypes.func.isRequired,
|
||||||
datasource: PropTypes.object,
|
datasource: PropTypes.object,
|
||||||
partitionColumn: PropTypes.string,
|
partitionColumn: PropTypes.string,
|
||||||
|
popoverRef: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
@ -73,8 +74,6 @@ function translateOperator(operator) {
|
|||||||
return operator;
|
return operator;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SINGLE_LINE_SELECT_CONTROL_HEIGHT = 30;
|
|
||||||
|
|
||||||
export default class AdhocFilterEditPopoverSimpleTabContent extends React.Component {
|
export default class AdhocFilterEditPopoverSimpleTabContent extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -86,11 +85,9 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
|
|||||||
this.refreshComparatorSuggestions = this.refreshComparatorSuggestions.bind(
|
this.refreshComparatorSuggestions = this.refreshComparatorSuggestions.bind(
|
||||||
this,
|
this,
|
||||||
);
|
);
|
||||||
this.multiComparatorRef = this.multiComparatorRef.bind(this);
|
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
suggestions: [],
|
suggestions: [],
|
||||||
multiComparatorHeight: SINGLE_LINE_SELECT_CONTROL_HEIGHT,
|
|
||||||
abortActiveRequest: null,
|
abortActiveRequest: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -101,21 +98,22 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
|
|||||||
autosize: false,
|
autosize: false,
|
||||||
clearable: false,
|
clearable: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.menuPortalProps = {
|
||||||
|
menuPortalTarget: props.popoverRef?.current || document.body,
|
||||||
|
menuPosition: 'fixed',
|
||||||
|
menuPlacement: 'bottom',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
UNSAFE_componentWillMount() {
|
||||||
this.refreshComparatorSuggestions();
|
this.refreshComparatorSuggestions();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.handleMultiComparatorInputHeightChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if (prevProps.adhocFilter.subject !== this.props.adhocFilter.subject) {
|
if (prevProps.adhocFilter.subject !== this.props.adhocFilter.subject) {
|
||||||
this.refreshComparatorSuggestions();
|
this.refreshComparatorSuggestions();
|
||||||
}
|
}
|
||||||
this.handleMultiComparatorInputHeightChange();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubjectChange(option) {
|
onSubjectChange(option) {
|
||||||
@ -192,27 +190,6 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMultiComparatorInputHeightChange() {
|
|
||||||
if (this.multiComparatorComponent) {
|
|
||||||
const multiComparatorDOMNode = this.multiComparatorComponent?.select
|
|
||||||
?.select.controlRef;
|
|
||||||
if (multiComparatorDOMNode) {
|
|
||||||
if (
|
|
||||||
multiComparatorDOMNode.clientHeight !==
|
|
||||||
this.state.multiComparatorHeight
|
|
||||||
) {
|
|
||||||
this.props.onHeightChange(
|
|
||||||
multiComparatorDOMNode.clientHeight -
|
|
||||||
this.state.multiComparatorHeight,
|
|
||||||
);
|
|
||||||
this.setState({
|
|
||||||
multiComparatorHeight: multiComparatorDOMNode.clientHeight,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshComparatorSuggestions() {
|
refreshComparatorSuggestions() {
|
||||||
const { datasource } = this.props;
|
const { datasource } = this.props;
|
||||||
const col = this.props.adhocFilter.subject;
|
const col = this.props.adhocFilter.subject;
|
||||||
@ -270,12 +247,6 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
multiComparatorRef(ref) {
|
|
||||||
if (ref) {
|
|
||||||
this.multiComparatorComponent = ref;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderSubjectOptionLabel(option) {
|
renderSubjectOptionLabel(option) {
|
||||||
return <FilterDefinitionOption option={option} />;
|
return <FilterDefinitionOption option={option} />;
|
||||||
}
|
}
|
||||||
@ -328,10 +299,11 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<>
|
||||||
<FormGroup className="adhoc-filter-simple-column-dropdown">
|
<FormGroup className="adhoc-filter-simple-column-dropdown">
|
||||||
<Select
|
<Select
|
||||||
{...this.selectProps}
|
{...this.selectProps}
|
||||||
|
{...this.menuPortalProps}
|
||||||
{...subjectSelectProps}
|
{...subjectSelectProps}
|
||||||
name="filter-column"
|
name="filter-column"
|
||||||
/>
|
/>
|
||||||
@ -339,6 +311,7 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
|
|||||||
<FormGroup>
|
<FormGroup>
|
||||||
<Select
|
<Select
|
||||||
{...this.selectProps}
|
{...this.selectProps}
|
||||||
|
{...this.menuPortalProps}
|
||||||
{...operatorSelectProps}
|
{...operatorSelectProps}
|
||||||
name="filter-operator"
|
name="filter-operator"
|
||||||
/>
|
/>
|
||||||
@ -347,6 +320,7 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
|
|||||||
{MULTI_OPERATORS.has(operator) ||
|
{MULTI_OPERATORS.has(operator) ||
|
||||||
this.state.suggestions.length > 0 ? (
|
this.state.suggestions.length > 0 ? (
|
||||||
<SelectControl
|
<SelectControl
|
||||||
|
{...this.menuPortalProps}
|
||||||
name="filter-value"
|
name="filter-value"
|
||||||
autoFocus
|
autoFocus
|
||||||
freeForm
|
freeForm
|
||||||
@ -357,7 +331,6 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
|
|||||||
onChange={this.onComparatorChange}
|
onChange={this.onComparatorChange}
|
||||||
showHeader={false}
|
showHeader={false}
|
||||||
noResultsText={t('type a value here')}
|
noResultsText={t('type a value here')}
|
||||||
selectRef={this.multiComparatorRef}
|
|
||||||
disabled={DISABLE_INPUT_OPERATORS.includes(operator)}
|
disabled={DISABLE_INPUT_OPERATORS.includes(operator)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@ -373,7 +346,7 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</span>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ export default class AdhocFilterEditPopoverSqlTabContent extends React.Component
|
|||||||
<SQLEditor
|
<SQLEditor
|
||||||
ref={this.handleAceEditorRef}
|
ref={this.handleAceEditorRef}
|
||||||
keywords={keywords}
|
keywords={keywords}
|
||||||
height={`${height - 100}px`}
|
height={`${height - 130}px`}
|
||||||
onChange={this.onSqlExpressionChange}
|
onChange={this.onSqlExpressionChange}
|
||||||
width="100%"
|
width="100%"
|
||||||
showGutter={false}
|
showGutter={false}
|
||||||
|
@ -22,7 +22,7 @@ import { FormGroup } from 'react-bootstrap';
|
|||||||
import Tabs from 'src/common/components/Tabs';
|
import Tabs from 'src/common/components/Tabs';
|
||||||
import Button from 'src/components/Button';
|
import Button from 'src/components/Button';
|
||||||
import Select from 'src/components/Select';
|
import Select from 'src/components/Select';
|
||||||
import { t } from '@superset-ui/core';
|
import { styled, t } from '@superset-ui/core';
|
||||||
import { ColumnOption } from '@superset-ui/chart-controls';
|
import { ColumnOption } from '@superset-ui/chart-controls';
|
||||||
|
|
||||||
import FormLabel from 'src/components/FormLabel';
|
import FormLabel from 'src/components/FormLabel';
|
||||||
@ -50,7 +50,11 @@ const defaultProps = {
|
|||||||
columns: [],
|
columns: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const startingWidth = 300;
|
const ResizeIcon = styled.i`
|
||||||
|
margin-left: ${({ theme }) => theme.gridUnit * 2}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const startingWidth = 320;
|
||||||
const startingHeight = 240;
|
const startingHeight = 240;
|
||||||
|
|
||||||
export default class AdhocMetricEditPopover extends React.Component {
|
export default class AdhocMetricEditPopover extends React.Component {
|
||||||
@ -65,17 +69,28 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||||||
this.onMouseUp = this.onMouseUp.bind(this);
|
this.onMouseUp = this.onMouseUp.bind(this);
|
||||||
this.handleAceEditorRef = this.handleAceEditorRef.bind(this);
|
this.handleAceEditorRef = this.handleAceEditorRef.bind(this);
|
||||||
this.refreshAceEditor = this.refreshAceEditor.bind(this);
|
this.refreshAceEditor = this.refreshAceEditor.bind(this);
|
||||||
|
|
||||||
|
this.popoverRef = React.createRef();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
adhocMetric: this.props.adhocMetric,
|
adhocMetric: this.props.adhocMetric,
|
||||||
width: startingWidth,
|
width: startingWidth,
|
||||||
height: startingHeight,
|
height: startingHeight,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.selectProps = {
|
this.selectProps = {
|
||||||
labelKey: 'label',
|
labelKey: 'label',
|
||||||
isMulti: false,
|
isMulti: false,
|
||||||
autosize: false,
|
autosize: false,
|
||||||
clearable: true,
|
clearable: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.menuPortalProps = {
|
||||||
|
menuPosition: 'fixed',
|
||||||
|
menuPlacement: 'bottom',
|
||||||
|
menuPortalTarget: this.popoverRef.current,
|
||||||
|
};
|
||||||
|
|
||||||
document.addEventListener('mouseup', this.onMouseUp);
|
document.addEventListener('mouseup', this.onMouseUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +230,7 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||||||
<div
|
<div
|
||||||
id="metrics-edit-popover"
|
id="metrics-edit-popover"
|
||||||
data-test="metrics-edit-popover"
|
data-test="metrics-edit-popover"
|
||||||
|
ref={this.popoverRef}
|
||||||
{...popoverProps}
|
{...popoverProps}
|
||||||
>
|
>
|
||||||
<Tabs
|
<Tabs
|
||||||
@ -237,6 +253,7 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||||||
<Select
|
<Select
|
||||||
name="select-column"
|
name="select-column"
|
||||||
{...this.selectProps}
|
{...this.selectProps}
|
||||||
|
{...this.menuPortalProps}
|
||||||
{...columnSelectProps}
|
{...columnSelectProps}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
@ -247,6 +264,7 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||||||
<Select
|
<Select
|
||||||
name="select-aggregate"
|
name="select-aggregate"
|
||||||
{...this.selectProps}
|
{...this.selectProps}
|
||||||
|
{...this.menuPortalProps}
|
||||||
{...aggregateSelectProps}
|
{...aggregateSelectProps}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
@ -264,7 +282,7 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||||||
showLoadingForImport
|
showLoadingForImport
|
||||||
ref={this.handleAceEditorRef}
|
ref={this.handleAceEditorRef}
|
||||||
keywords={keywords}
|
keywords={keywords}
|
||||||
height={`${this.state.height - 43}px`}
|
height={`${this.state.height - 80}px`}
|
||||||
onChange={this.onSqlExpressionChange}
|
onChange={this.onSqlExpressionChange}
|
||||||
width="100%"
|
width="100%"
|
||||||
showGutter={false}
|
showGutter={false}
|
||||||
@ -285,19 +303,6 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
|
||||||
disabled={!stateIsValid}
|
|
||||||
buttonStyle={
|
|
||||||
hasUnsavedChanges && stateIsValid ? 'primary' : 'default'
|
|
||||||
}
|
|
||||||
buttonSize="small"
|
|
||||||
className="m-r-5"
|
|
||||||
data-test="AdhocMetricEdit#save"
|
|
||||||
onClick={this.onSave}
|
|
||||||
cta
|
|
||||||
>
|
|
||||||
Save
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
buttonSize="small"
|
buttonSize="small"
|
||||||
onClick={this.props.onClose}
|
onClick={this.props.onClose}
|
||||||
@ -306,7 +311,19 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||||||
>
|
>
|
||||||
Close
|
Close
|
||||||
</Button>
|
</Button>
|
||||||
<i
|
<Button
|
||||||
|
disabled={!stateIsValid}
|
||||||
|
buttonStyle={
|
||||||
|
hasUnsavedChanges && stateIsValid ? 'primary' : 'default'
|
||||||
|
}
|
||||||
|
buttonSize="small"
|
||||||
|
data-test="AdhocMetricEdit#save"
|
||||||
|
onClick={this.onSave}
|
||||||
|
cta
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
<ResizeIcon
|
||||||
role="button"
|
role="button"
|
||||||
aria-label="Resize"
|
aria-label="Resize"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
@ -53,6 +53,9 @@ const propTypes = {
|
|||||||
filterOption: PropTypes.func,
|
filterOption: PropTypes.func,
|
||||||
promptTextCreator: PropTypes.func,
|
promptTextCreator: PropTypes.func,
|
||||||
commaChoosesOption: PropTypes.bool,
|
commaChoosesOption: PropTypes.bool,
|
||||||
|
menuPortalTarget: PropTypes.element,
|
||||||
|
menuPosition: PropTypes.string,
|
||||||
|
menuPlacement: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
@ -219,6 +222,9 @@ export default class SelectControl extends React.PureComponent {
|
|||||||
filterOption: this.props.filterOption,
|
filterOption: this.props.filterOption,
|
||||||
promptTextCreator: this.props.promptTextCreator,
|
promptTextCreator: this.props.promptTextCreator,
|
||||||
ignoreAccents: false,
|
ignoreAccents: false,
|
||||||
|
menuPortalTarget: this.props.menuPortalTarget,
|
||||||
|
menuPosition: this.props.menuPosition,
|
||||||
|
menuPlacement: this.props.menuPlacement,
|
||||||
};
|
};
|
||||||
|
|
||||||
let SelectComponent;
|
let SelectComponent;
|
||||||
|
Loading…
Reference in New Issue
Block a user