Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(explore): Drag and drop UX improvements #13598

Merged
merged 5 commits into from
Mar 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export const DndLabelsContainer = styled.div<{
}>`
padding: ${({ theme }) => theme.gridUnit}px;
border: ${({ canDrop, isOver, theme }) => {
if (isOver && canDrop) {
if (canDrop) {
return `dashed 1px ${theme.colors.info.dark1}`;
}
if (isOver && !canDrop) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ export const DndColumnSelect = (props: LabelProps) => {

return (
<DndSelectLabel<string | string[], ColumnMeta[]>
values={values}
onDrop={onDrop}
canDrop={canDrop}
valuesRenderer={valuesRenderer}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
* under the License.
*/
import React, { useEffect, useMemo, useState } from 'react';
import { logging, SupersetClient, t } from '@superset-ui/core';
import { ColumnMeta, Metric } from '@superset-ui/chart-controls';
import { logging, SupersetClient, t, Metric } from '@superset-ui/core';
import { ColumnMeta } from '@superset-ui/chart-controls';
import { Tooltip } from 'src/common/components/Tooltip';
import { OPERATORS } from 'src/explore/constants';
import { OptionSortType } from 'src/explore/types';
Expand Down Expand Up @@ -300,7 +300,6 @@ export const DndFilterSelect = (props: DndFilterSelectProps) => {
return (
<>
<DndSelectLabel<OptionValueType, OptionValueType[]>
values={values}
onDrop={(item: DatasourcePanelDndItem) => {
setDroppedItem(item.value);
togglePopover(true);
Expand All @@ -313,7 +312,7 @@ export const DndFilterSelect = (props: DndFilterSelectProps) => {
DndItemType.MetricOption,
DndItemType.AdhocMetricOption,
]}
placeholderText={t('Drop columns or metrics')}
ghostButtonText={t('Drop columns or metrics')}
{...props}
/>
<AdhocFilterPopoverTrigger
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,41 +241,35 @@ export const DndMetricSelect = (props: any) => {
togglePopover(false);
};

const { savedMetric, adhocMetric } = useMemo(() => {
if (droppedItem?.type === 'column') {
const itemValue = droppedItem?.value as ColumnMeta;
return {
savedMetric: {} as savedMetricType,
adhocMetric: new AdhocMetric({
column: { column_name: itemValue?.column_name },
}),
};
const handleDrop = (item: DatasourcePanelDndItem) => {
if (item.type === DndItemType.Metric) {
onNewMetric(item.value as Metric);
}
if (item.type === DndItemType.Column) {
setDroppedItem(item);
togglePopover(true);
}
if (droppedItem?.type === 'metric') {
const itemValue = droppedItem?.value as savedMetricType;
return {
savedMetric: itemValue,
adhocMetric: new AdhocMetric({ isNew: true }),
};
};

const adhocMetric = useMemo(() => {
if (droppedItem?.type === DndItemType.Column) {
const itemValue = droppedItem?.value as ColumnMeta;
return new AdhocMetric({
column: { column_name: itemValue?.column_name },
});
}
return {
savedMetric: {} as savedMetricType,
adhocMetric: new AdhocMetric({ isNew: true }),
};
return new AdhocMetric({ isNew: true });
}, [droppedItem?.type, droppedItem?.value]);

return (
<div className="metrics-select">
<DndSelectLabel<OptionValueType, OptionValueType[]>
values={value}
onDrop={(item: DatasourcePanelDndItem) => {
setDroppedItem(item);
togglePopover(true);
}}
onDrop={handleDrop}
canDrop={canDrop}
valuesRenderer={valuesRenderer}
accept={[DndItemType.Column, DndItemType.Metric]}
placeholderText={t('Drop columns or metrics')}
ghostButtonText={t('Drop columns or metrics')}
displayGhostButton={multi || value.length === 0}
{...props}
/>
<AdhocMetricPopoverTrigger
Expand All @@ -286,7 +280,7 @@ export const DndMetricSelect = (props: any) => {
props.savedMetrics,
props.value,
)}
savedMetric={savedMetric}
savedMetric={{} as savedMetricType}
datasourceType={props.datasourceType}
isControlledComponent
visible={newMetricPopoverVisible}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/
import React from 'react';
import { useDrop } from 'react-dnd';
import { isEmpty } from 'lodash';
import { t, useTheme } from '@superset-ui/core';
import ControlHeader from 'src/explore/components/ControlHeader';
import {
Expand All @@ -30,9 +29,10 @@ import { DatasourcePanelDndItem } from 'src/explore/components/DatasourcePanel/t
import Icon from 'src/components/Icon';
import { DndColumnSelectProps } from './types';

export default function DndSelectLabel<T, O>(
props: DndColumnSelectProps<T, O>,
) {
export default function DndSelectLabel<T, O>({
displayGhostButton = true,
...props
}: DndColumnSelectProps<T, O>) {
const theme = useTheme();

const [{ isOver, canDrop }, datasourcePanelDrop] = useDrop({
Expand All @@ -51,11 +51,11 @@ export default function DndSelectLabel<T, O>(
}),
});

function renderPlaceHolder() {
function renderGhostButton() {
return (
<AddControlLabel cancelHover>
<Icon name="plus-small" color={theme.colors.grayscale.light1} />
{t(props.placeholderText || 'Drop columns')}
{t(props.ghostButtonText || 'Drop columns')}
</AddControlLabel>
);
}
Expand All @@ -66,7 +66,8 @@ export default function DndSelectLabel<T, O>(
<ControlHeader {...props} />
</HeaderContainer>
<DndLabelsContainer canDrop={canDrop} isOver={isOver}>
{isEmpty(props.values) ? renderPlaceHolder() : props.valuesRenderer()}
{props.valuesRenderer()}
{displayGhostButton && renderGhostButton()}
</DndLabelsContainer>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
* under the License.
*/
import { ReactNode } from 'react';
import { ColumnMeta, Metric } from '@superset-ui/chart-controls';
import { Metric } from '@superset-ui/core';
import { ColumnMeta } from '@superset-ui/chart-controls';
import { DatasourcePanelDndItem } from '../../DatasourcePanel/types';
import { DndItemType } from '../../DndItemType';

Expand Down Expand Up @@ -45,12 +46,12 @@ export interface DndColumnSelectProps<
T = string[] | string,
O = string[] | string
> extends LabelProps<T> {
values?: O;
onDrop: (item: DatasourcePanelDndItem) => void;
canDrop: (item: DatasourcePanelDndItem) => boolean;
valuesRenderer: () => ReactNode;
accept: DndItemType | DndItemType[];
placeholderText?: string;
ghostButtonText?: string;
displayGhostButton?: boolean;
}

export type OptionValueType = Record<string, any>;
Expand Down