feat(explore): Make metric title respond to changes immediately (#12747)

* Make metric title respond to changes immediately

* Bug fix

* Change type to Metric

* Bug fix
This commit is contained in:
Kamil Gabryjelski 2021-01-28 07:58:39 +01:00 committed by GitHub
parent 41b990f72d
commit 14de7b4791
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 26 deletions

View File

@ -56,6 +56,7 @@ function setup(overrides) {
onChange, onChange,
onClose, onClose,
onResize: () => {}, onResize: () => {},
getCurrentLabel: () => {},
columns, columns,
...overrides, ...overrides,
}; };

View File

@ -42,14 +42,11 @@ const propTypes = {
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
onResize: PropTypes.func.isRequired, onResize: PropTypes.func.isRequired,
getCurrentTab: PropTypes.func, getCurrentTab: PropTypes.func,
getCurrentLabel: PropTypes.func,
columns: PropTypes.arrayOf(columnType), columns: PropTypes.arrayOf(columnType),
savedMetricsOptions: PropTypes.arrayOf(savedMetricType), savedMetricsOptions: PropTypes.arrayOf(savedMetricType),
savedMetric: savedMetricType, savedMetric: savedMetricType,
datasourceType: PropTypes.string, datasourceType: PropTypes.string,
title: PropTypes.shape({
label: PropTypes.string,
hasCustomLabel: PropTypes.bool,
}),
}; };
const defaultProps = { const defaultProps = {
@ -72,7 +69,7 @@ export const SAVED_TAB_KEY = 'SAVED';
const startingWidth = 320; const startingWidth = 320;
const startingHeight = 240; const startingHeight = 240;
export default class AdhocMetricEditPopover extends React.Component { export default class AdhocMetricEditPopover extends React.PureComponent {
// "Saved" is a default tab unless there are no saved metrics for dataset // "Saved" is a default tab unless there are no saved metrics for dataset
defaultActiveTabKey = defaultActiveTabKey =
(this.props.savedMetric.metric_name || this.props.adhocMetric.isNew) && (this.props.savedMetric.metric_name || this.props.adhocMetric.isNew) &&
@ -110,20 +107,31 @@ export default class AdhocMetricEditPopover extends React.Component {
this.props.getCurrentTab(this.defaultActiveTabKey); this.props.getCurrentTab(this.defaultActiveTabKey);
} }
componentDidUpdate(prevProps, prevState) {
if (
prevState.adhocMetric?.sqlExpression !==
this.state.adhocMetric?.sqlExpression ||
prevState.adhocMetric?.aggregate !== this.state.adhocMetric?.aggregate ||
prevState.adhocMetric?.column?.column_name !==
this.state.adhocMetric?.column?.column_name ||
prevState.savedMetric?.metric_name !== this.state.savedMetric?.metric_name
) {
this.props.getCurrentLabel({
savedMetricLabel:
this.state.savedMetric?.verbose_name ||
this.state.savedMetric?.metric_name,
adhocMetricLabel: this.state.adhocMetric?.getDefaultLabel(),
});
}
}
componentWillUnmount() { componentWillUnmount() {
document.removeEventListener('mouseup', this.onMouseUp); document.removeEventListener('mouseup', this.onMouseUp);
document.removeEventListener('mousemove', this.onMouseMove); document.removeEventListener('mousemove', this.onMouseMove);
} }
onSave() { onSave() {
const { title } = this.props;
const { hasCustomLabel } = title;
let { label } = title;
const { adhocMetric, savedMetric } = this.state; const { adhocMetric, savedMetric } = this.state;
const metricLabel = adhocMetric.label;
if (!hasCustomLabel) {
label = metricLabel;
}
const metric = savedMetric?.metric_name ? savedMetric : adhocMetric; const metric = savedMetric?.metric_name ? savedMetric : adhocMetric;
const oldMetric = this.props.savedMetric?.metric_name const oldMetric = this.props.savedMetric?.metric_name
@ -132,8 +140,6 @@ export default class AdhocMetricEditPopover extends React.Component {
this.props.onChange( this.props.onChange(
{ {
...metric, ...metric,
label,
hasCustomLabel,
}, },
oldMetric, oldMetric,
); );

View File

@ -17,6 +17,7 @@
* under the License. * under the License.
*/ */
import React, { ReactNode } from 'react'; import React, { ReactNode } from 'react';
import { Metric } from '@superset-ui/core';
import Popover from 'src/common/components/Popover'; import Popover from 'src/common/components/Popover';
import AdhocMetricEditPopoverTitle from 'src/explore/components/controls/MetricControl/AdhocMetricEditPopoverTitle'; import AdhocMetricEditPopoverTitle from 'src/explore/components/controls/MetricControl/AdhocMetricEditPopoverTitle';
import AdhocMetricEditPopover, { import AdhocMetricEditPopover, {
@ -27,7 +28,7 @@ import { savedMetricType } from './types';
export type AdhocMetricPopoverTriggerProps = { export type AdhocMetricPopoverTriggerProps = {
adhocMetric: AdhocMetric; adhocMetric: AdhocMetric;
onMetricEdit: () => void; onMetricEdit(newMetric: Metric, oldMetric: Metric): void;
columns: { column_name: string; type: string }[]; columns: { column_name: string; type: string }[];
savedMetricsOptions: savedMetricType[]; savedMetricsOptions: savedMetricType[];
savedMetric: savedMetricType; savedMetric: savedMetricType;
@ -39,6 +40,7 @@ export type AdhocMetricPopoverTriggerProps = {
export type AdhocMetricPopoverTriggerState = { export type AdhocMetricPopoverTriggerState = {
popoverVisible: boolean; popoverVisible: boolean;
title: { label: string; hasCustomLabel: boolean }; title: { label: string; hasCustomLabel: boolean };
currentLabel: string;
labelModified: boolean; labelModified: boolean;
isTitleEditDisabled: boolean; isTitleEditDisabled: boolean;
}; };
@ -53,26 +55,38 @@ class AdhocMetricPopoverTrigger extends React.PureComponent<
this.onLabelChange = this.onLabelChange.bind(this); this.onLabelChange = this.onLabelChange.bind(this);
this.closePopover = this.closePopover.bind(this); this.closePopover = this.closePopover.bind(this);
this.togglePopover = this.togglePopover.bind(this); this.togglePopover = this.togglePopover.bind(this);
this.getCurrentTab = this.getCurrentTab.bind(this);
this.getCurrentLabel = this.getCurrentLabel.bind(this);
this.onChange = this.onChange.bind(this);
this.state = { this.state = {
popoverVisible: false, popoverVisible: false,
title: { title: {
label: props.adhocMetric.label, label: props.adhocMetric.label,
hasCustomLabel: props.adhocMetric.hasCustomLabel, hasCustomLabel: props.adhocMetric.hasCustomLabel,
}, },
currentLabel: '',
labelModified: false, labelModified: false,
isTitleEditDisabled: false, isTitleEditDisabled: false,
}; };
} }
onLabelChange(e: any) { onLabelChange(e: any) {
const { verbose_name, metric_name } = this.props.savedMetric;
const defaultMetricLabel = this.props.adhocMetric?.getDefaultLabel();
const label = e.target.value; const label = e.target.value;
this.setState({ this.setState(state => ({
title: { title: {
label: label || this.props.adhocMetric.label, label:
label ||
state.currentLabel ||
verbose_name ||
metric_name ||
defaultMetricLabel,
hasCustomLabel: !!label, hasCustomLabel: !!label,
}, },
labelModified: true, labelModified: true,
}); }));
} }
onPopoverResize() { onPopoverResize() {
@ -92,13 +106,51 @@ class AdhocMetricPopoverTrigger extends React.PureComponent<
}); });
} }
getCurrentTab(tab: string) {
this.setState({
isTitleEditDisabled: tab === SAVED_TAB_KEY,
});
}
getCurrentLabel({
savedMetricLabel,
adhocMetricLabel,
}: {
savedMetricLabel: string;
adhocMetricLabel: string;
}) {
const currentLabel = savedMetricLabel || adhocMetricLabel;
this.setState({
currentLabel,
labelModified: true,
});
if (savedMetricLabel || !this.state.title.hasCustomLabel) {
this.setState({
title: {
label: currentLabel,
hasCustomLabel: false,
},
});
}
}
onChange(newMetric: Metric, oldMetric: Metric) {
this.props.onMetricEdit({ ...newMetric, ...this.state.title }, oldMetric);
}
render() { render() {
const { adhocMetric, savedMetric } = this.props; const { adhocMetric, savedMetric } = this.props;
const { verbose_name, metric_name } = savedMetric; const { verbose_name, metric_name } = savedMetric;
const { label, hasCustomLabel } = adhocMetric; const { hasCustomLabel, label } = adhocMetric;
const adhocMetricLabel = hasCustomLabel
? label
: adhocMetric.getDefaultLabel();
const title = this.state.labelModified const title = this.state.labelModified
? this.state.title ? this.state.title
: { label: verbose_name || metric_name || label, hasCustomLabel }; : {
label: verbose_name || metric_name || adhocMetricLabel,
hasCustomLabel,
};
const overlayContent = ( const overlayContent = (
<AdhocMetricEditPopover <AdhocMetricEditPopover
@ -110,12 +162,9 @@ class AdhocMetricPopoverTrigger extends React.PureComponent<
datasourceType={this.props.datasourceType} datasourceType={this.props.datasourceType}
onResize={this.onPopoverResize} onResize={this.onPopoverResize}
onClose={this.closePopover} onClose={this.closePopover}
onChange={this.props.onMetricEdit} onChange={this.onChange}
getCurrentTab={(tab: string) => getCurrentTab={this.getCurrentTab}
this.setState({ getCurrentLabel={this.getCurrentLabel}
isTitleEditDisabled: tab === SAVED_TAB_KEY,
})
}
/> />
); );