mirror of https://github.com/apache/superset.git
fix: Cannot re-order metrics by drag and drop (#19876)
* fix: cannot-re-order-metrics-by-drag-and-drop * add tests
This commit is contained in:
parent
481ccfe0a6
commit
e4fca89217
|
@ -47,6 +47,7 @@ export interface MetricOptionProps {
|
||||||
showType?: boolean;
|
showType?: boolean;
|
||||||
url?: string;
|
url?: string;
|
||||||
labelRef?: React.RefObject<any>;
|
labelRef?: React.RefObject<any>;
|
||||||
|
shouldShowTooltip?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MetricOption({
|
export function MetricOption({
|
||||||
|
@ -55,6 +56,7 @@ export function MetricOption({
|
||||||
openInNewWindow = false,
|
openInNewWindow = false,
|
||||||
showFormula = true,
|
showFormula = true,
|
||||||
showType = false,
|
showType = false,
|
||||||
|
shouldShowTooltip = true,
|
||||||
url = '',
|
url = '',
|
||||||
}: MetricOptionProps) {
|
}: MetricOptionProps) {
|
||||||
const verbose = metric.verbose_name || metric.metric_name || metric.label;
|
const verbose = metric.verbose_name || metric.metric_name || metric.label;
|
||||||
|
@ -66,6 +68,20 @@ export function MetricOption({
|
||||||
verbose
|
verbose
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const label = (
|
||||||
|
<span
|
||||||
|
className="option-label metric-option-label"
|
||||||
|
css={(theme: SupersetTheme) =>
|
||||||
|
css`
|
||||||
|
margin-right: ${theme.gridUnit}px;
|
||||||
|
`
|
||||||
|
}
|
||||||
|
ref={labelRef}
|
||||||
|
>
|
||||||
|
{link}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
|
||||||
const warningMarkdown = metric.warning_markdown || metric.warning_text;
|
const warningMarkdown = metric.warning_markdown || metric.warning_text;
|
||||||
|
|
||||||
const [tooltipText, setTooltipText] = useState<ReactNode>(metric.metric_name);
|
const [tooltipText, setTooltipText] = useState<ReactNode>(metric.metric_name);
|
||||||
|
@ -77,19 +93,13 @@ export function MetricOption({
|
||||||
return (
|
return (
|
||||||
<FlexRowContainer className="metric-option">
|
<FlexRowContainer className="metric-option">
|
||||||
{showType && <ColumnTypeLabel type="expression" />}
|
{showType && <ColumnTypeLabel type="expression" />}
|
||||||
<Tooltip id="metric-name-tooltip" title={tooltipText}>
|
{shouldShowTooltip ? (
|
||||||
<span
|
<Tooltip id="metric-name-tooltip" title={tooltipText}>
|
||||||
className="option-label metric-option-label"
|
{label}
|
||||||
css={(theme: SupersetTheme) =>
|
</Tooltip>
|
||||||
css`
|
) : (
|
||||||
margin-right: ${theme.gridUnit}px;
|
label
|
||||||
`
|
)}
|
||||||
}
|
|
||||||
ref={labelRef}
|
|
||||||
>
|
|
||||||
{link}
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
{showFormula && metric.expression && (
|
{showFormula && metric.expression && (
|
||||||
<SQLPopover sqlExpression={metric.expression} />
|
<SQLPopover sqlExpression={metric.expression} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -17,7 +17,12 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen } from 'spec/helpers/testing-library';
|
import {
|
||||||
|
render,
|
||||||
|
screen,
|
||||||
|
within,
|
||||||
|
fireEvent,
|
||||||
|
} from 'spec/helpers/testing-library';
|
||||||
import { DndMetricSelect } from 'src/explore/components/controls/DndColumnSelectControl/DndMetricSelect';
|
import { DndMetricSelect } from 'src/explore/components/controls/DndColumnSelectControl/DndMetricSelect';
|
||||||
import { AGGREGATES } from 'src/explore/constants';
|
import { AGGREGATES } from 'src/explore/constants';
|
||||||
import { EXPRESSION_TYPES } from '../MetricControl/AdhocMetric';
|
import { EXPRESSION_TYPES } from '../MetricControl/AdhocMetric';
|
||||||
|
@ -27,6 +32,7 @@ const defaultProps = {
|
||||||
{
|
{
|
||||||
metric_name: 'metric_a',
|
metric_name: 'metric_a',
|
||||||
expression: 'expression_a',
|
expression: 'expression_a',
|
||||||
|
verbose_name: 'metric_a',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
metric_name: 'metric_b',
|
metric_name: 'metric_b',
|
||||||
|
@ -282,3 +288,32 @@ test('update adhoc metric name when column label in dataset changes', () => {
|
||||||
expect(screen.getByText('SUM(new col A name)')).toBeVisible();
|
expect(screen.getByText('SUM(new col A name)')).toBeVisible();
|
||||||
expect(screen.getByText('SUM(new col B name)')).toBeVisible();
|
expect(screen.getByText('SUM(new col B name)')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('can drag metrics', async () => {
|
||||||
|
const metricValues = ['metric_a', 'metric_b', adhocMetricB];
|
||||||
|
render(<DndMetricSelect {...defaultProps} value={metricValues} multi />, {
|
||||||
|
useDnd: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByText('metric_a')).toBeVisible();
|
||||||
|
expect(screen.getByText('Metric B')).toBeVisible();
|
||||||
|
|
||||||
|
const container = screen.getByTestId('dnd-labels-container');
|
||||||
|
expect(container.childElementCount).toBe(4);
|
||||||
|
|
||||||
|
const firstMetric = container.children[0] as HTMLElement;
|
||||||
|
const lastMetric = container.children[2] as HTMLElement;
|
||||||
|
expect(within(firstMetric).getByText('metric_a')).toBeVisible();
|
||||||
|
expect(within(lastMetric).getByText('SUM(Column B)')).toBeVisible();
|
||||||
|
|
||||||
|
fireEvent.mouseOver(within(firstMetric).getByText('metric_a'));
|
||||||
|
expect(await screen.findByText('Metric name')).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.dragStart(firstMetric);
|
||||||
|
fireEvent.dragEnter(lastMetric);
|
||||||
|
fireEvent.dragOver(lastMetric);
|
||||||
|
fireEvent.drop(lastMetric);
|
||||||
|
|
||||||
|
expect(within(firstMetric).getByText('SUM(Column B)')).toBeVisible();
|
||||||
|
expect(within(lastMetric).getByText('metric_a')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
|
@ -87,7 +87,11 @@ export default function DndSelectLabel({
|
||||||
<HeaderContainer>
|
<HeaderContainer>
|
||||||
<ControlHeader {...props} />
|
<ControlHeader {...props} />
|
||||||
</HeaderContainer>
|
</HeaderContainer>
|
||||||
<DndLabelsContainer canDrop={canDrop} isOver={isOver}>
|
<DndLabelsContainer
|
||||||
|
data-test="dnd-labels-container"
|
||||||
|
canDrop={canDrop}
|
||||||
|
isOver={isOver}
|
||||||
|
>
|
||||||
{props.valuesRenderer()}
|
{props.valuesRenderer()}
|
||||||
{displayGhostButton && renderGhostButton()}
|
{displayGhostButton && renderGhostButton()}
|
||||||
</DndLabelsContainer>
|
</DndLabelsContainer>
|
||||||
|
|
|
@ -279,7 +279,13 @@ export const OptionControlLabel = ({
|
||||||
labelRef.current.scrollWidth > labelRef.current.clientWidth);
|
labelRef.current.scrollWidth > labelRef.current.clientWidth);
|
||||||
|
|
||||||
if (savedMetric && hasMetricName) {
|
if (savedMetric && hasMetricName) {
|
||||||
return <StyledMetricOption metric={savedMetric} labelRef={labelRef} />;
|
return (
|
||||||
|
<StyledMetricOption
|
||||||
|
metric={savedMetric}
|
||||||
|
labelRef={labelRef}
|
||||||
|
shouldShowTooltip={!isDragging}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!shouldShowTooltip) {
|
if (!shouldShowTooltip) {
|
||||||
return <LabelText ref={labelRef}>{label}</LabelText>;
|
return <LabelText ref={labelRef}>{label}</LabelText>;
|
||||||
|
|
Loading…
Reference in New Issue