Skip to content

Commit

Permalink
feat: Implement drag & drop for metrics and filters labels (#12184)
Browse files Browse the repository at this point in the history
  • Loading branch information
kgabryje committed Dec 25, 2020
1 parent 74f3faf commit f3ab1f4
Show file tree
Hide file tree
Showing 13 changed files with 251 additions and 22 deletions.
Expand Up @@ -71,7 +71,7 @@ function setup(overrides) {
...overrides,
};
const wrapper = shallow(<AdhocFilterControl {...props} />);
const component = wrapper.dive().shallow();
const component = wrapper.dive().dive().shallow();
return { wrapper, component, onChange };
}

Expand Down
Expand Up @@ -56,6 +56,6 @@ describe('AdhocFilterOption', () => {
const popover = overlay.find(Popover);
expect(popover).toHaveLength(1);
expect(popover.props().defaultVisible).toBe(false);
expect(overlay.find('OptionControlLabel')).toExist();
expect(overlay.find('DraggableOptionControlLabel')).toExist();
});
});
Expand Up @@ -45,6 +45,9 @@ function setup(overrides) {
savedMetrics: [],
onMetricEdit,
columns,
onMoveLabel: () => {},
onDropLabel: () => {},
index: 0,
...overrides,
};
const wrapper = shallow(<AdhocMetricOption {...props} />)
Expand All @@ -57,7 +60,7 @@ describe('AdhocMetricOption', () => {
it('renders an overlay trigger wrapper for the label', () => {
const { wrapper } = setup();
expect(wrapper.find(Popover)).toExist();
expect(wrapper.find('OptionControlLabel')).toExist();
expect(wrapper.find('DraggableOptionControlLabel')).toExist();
});

it('overwrites the adhocMetric in state with onLabelChange', () => {
Expand Down
Expand Up @@ -53,7 +53,7 @@ function setup(overrides) {
...overrides,
};
const wrapper = shallow(<MetricsControl {...props} />);
const component = wrapper.dive().shallow();
const component = wrapper.dive().dive().shallow();
return { wrapper, component, onChange };
}

Expand Down
Expand Up @@ -120,7 +120,9 @@ describe('VerifiedMetricsControl', () => {
onChange: mockOnChange,
});

const child = wrapper.find(MetricsControl);
const child = wrapper.find(MetricsControl) as ReactWrapper<{
onChange: (str: string[]) => void;
}>;
child.props().onChange(['abc']);

expect(child.length).toBe(1);
Expand Down
23 changes: 23 additions & 0 deletions superset-frontend/src/explore/DndContextProvider.js
@@ -0,0 +1,23 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// TODO: convert to .ts after we upgrade react-dnd
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

export default DragDropContext(HTML5Backend);
15 changes: 13 additions & 2 deletions superset-frontend/src/explore/components/AdhocFilterOption.jsx
Expand Up @@ -22,7 +22,8 @@ import AdhocFilter from '../AdhocFilter';
import columnType from '../propTypes/columnType';
import adhocMetricType from '../propTypes/adhocMetricType';
import AdhocFilterPopoverTrigger from './AdhocFilterPopoverTrigger';
import { OptionControlLabel } from './OptionControls';
import { DraggableOptionControlLabel } from './OptionControls';
import { OPTION_TYPES } from './optionTypes';

const propTypes = {
adhocFilter: PropTypes.instanceOf(AdhocFilter).isRequired,
Expand All @@ -37,6 +38,9 @@ const propTypes = {
).isRequired,
datasource: PropTypes.object,
partitionColumn: PropTypes.string,
onMoveLabel: PropTypes.func,
onDropLabel: PropTypes.func,
index: PropTypes.number,
};

const AdhocFilterOption = ({
Expand All @@ -46,6 +50,9 @@ const AdhocFilterOption = ({
onFilterEdit,
onRemoveFilter,
partitionColumn,
onMoveLabel,
onDropLabel,
index,
}) => (
<AdhocFilterPopoverTrigger
adhocFilter={adhocFilter}
Expand All @@ -54,9 +61,13 @@ const AdhocFilterOption = ({
onFilterEdit={onFilterEdit}
partitionColumn={partitionColumn}
>
<OptionControlLabel
<DraggableOptionControlLabel
label={adhocFilter.getDefaultLabel()}
onRemove={onRemoveFilter}
onMoveLabel={onMoveLabel}
onDropLabel={onDropLabel}
index={index}
type={OPTION_TYPES.filter}
isAdhoc
/>
</AdhocFilterPopoverTrigger>
Expand Down
15 changes: 13 additions & 2 deletions superset-frontend/src/explore/components/AdhocMetricOption.jsx
Expand Up @@ -21,8 +21,9 @@ import PropTypes from 'prop-types';
import AdhocMetric from '../AdhocMetric';
import columnType from '../propTypes/columnType';
import savedMetricType from '../propTypes/savedMetricType';
import { OptionControlLabel } from './OptionControls';
import { DraggableOptionControlLabel } from './OptionControls';
import AdhocMetricPopoverTrigger from './AdhocMetricPopoverTrigger';
import { OPTION_TYPES } from './optionTypes';

const propTypes = {
adhocMetric: PropTypes.instanceOf(AdhocMetric),
Expand All @@ -32,6 +33,9 @@ const propTypes = {
savedMetrics: PropTypes.arrayOf(savedMetricType),
savedMetric: savedMetricType,
datasourceType: PropTypes.string,
onMoveLabel: PropTypes.func,
onDropLabel: PropTypes.func,
index: PropTypes.number,
};

class AdhocMetricOption extends React.PureComponent {
Expand All @@ -53,6 +57,9 @@ class AdhocMetricOption extends React.PureComponent {
savedMetrics,
savedMetric,
datasourceType,
onMoveLabel,
onDropLabel,
index,
} = this.props;
return (
<AdhocMetricPopoverTrigger
Expand All @@ -63,10 +70,14 @@ class AdhocMetricOption extends React.PureComponent {
savedMetric={savedMetric}
datasourceType={datasourceType}
>
<OptionControlLabel
<DraggableOptionControlLabel
savedMetric={savedMetric}
label={adhocMetric.label}
onRemove={this.onRemoveMetric}
onMoveLabel={onMoveLabel}
onDropLabel={onDropLabel}
index={index}
type={OPTION_TYPES.metric}
isAdhoc
isFunction
/>
Expand Down
23 changes: 20 additions & 3 deletions superset-frontend/src/explore/components/MetricDefinitionValue.jsx
Expand Up @@ -18,18 +18,21 @@
*/
import React from 'react';
import PropTypes from 'prop-types';

import AdhocMetricOption from './AdhocMetricOption';
import AdhocMetric from '../AdhocMetric';
import columnType from '../propTypes/columnType';
import savedMetricType from '../propTypes/savedMetricType';
import adhocMetricType from '../propTypes/adhocMetricType';
import { OptionControlLabel } from './OptionControls';
import { DraggableOptionControlLabel } from './OptionControls';
import { OPTION_TYPES } from './optionTypes';

const propTypes = {
option: PropTypes.oneOfType([savedMetricType, adhocMetricType]).isRequired,
index: PropTypes.number.isRequired,
onMetricEdit: PropTypes.func,
onRemoveMetric: PropTypes.func,
onMoveLabel: PropTypes.func,
onDropLabel: PropTypes.func,
columns: PropTypes.arrayOf(columnType),
savedMetrics: PropTypes.arrayOf(savedMetricType),
multi: PropTypes.bool,
Expand All @@ -43,6 +46,9 @@ export default function MetricDefinitionValue({
columns,
savedMetrics,
datasourceType,
onMoveLabel,
onDropLabel,
index,
}) {
const getSavedMetricByName = metricName =>
savedMetrics.find(metric => metric.metric_name === metricName);
Expand All @@ -65,14 +71,25 @@ export default function MetricDefinitionValue({
savedMetrics,
datasourceType,
adhocMetric,
onMoveLabel,
onDropLabel,
index,
savedMetric: savedMetric ?? {},
};

return <AdhocMetricOption {...metricOptionProps} />;
}
if (typeof option === 'string') {
return (
<OptionControlLabel label={option} onRemove={onRemoveMetric} isFunction />
<DraggableOptionControlLabel
label={option}
onRemove={onRemoveMetric}
onMoveLabel={onMoveLabel}
onDropLabel={onDropLabel}
type={OPTION_TYPES.metric}
index={index}
isFunction
/>
);
}
return null;
Expand Down

0 comments on commit f3ab1f4

Please sign in to comment.