Skip to content

Commit

Permalink
fix(Explore): Show the tooltip only when label does not fit the conta…
Browse files Browse the repository at this point in the history
…iner in METRICS/FILTERS/GROUP BY/SORT BY of the DATA panel (apache#16060)

* Implement dynamic tooltip

* Normalize and consolidate

* Clean up

* Refactor and clean up

* Remove unnecessary var

* Fix type import

* Update superset-frontend/src/explore/components/controls/OptionControls/index.tsx

Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>

* Remove unnecessary styled span

* Show full tooltip title

* Force show tooltip

* Force show tooltip D&D off

Co-authored-by: Ville Brofeldt <ville.v.brofeldt@gmail.com>
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
  • Loading branch information
3 people authored Aug 12, 2021
1 parent 2c5731a commit a1e18ed
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import OptionWrapper from 'src/explore/components/controls/DndColumnSelectContro
import { OptionSelector } from 'src/explore/components/controls/DndColumnSelectControl/utils';
import { DatasourcePanelDndItem } from 'src/explore/components/DatasourcePanel/types';
import { DndItemType } from 'src/explore/components/DndItemType';
import { StyledColumnOption } from 'src/explore/components/optionRenderers';
import { useComponentDidUpdate } from 'src/common/hooks/useComponentDidUpdate';

export const DndColumnSelect = (props: LabelProps) => {
Expand Down Expand Up @@ -121,9 +120,8 @@ export const DndColumnSelect = (props: LabelProps) => {
onShiftOptions={onShiftOptions}
type={`${DndItemType.ColumnOption}_${name}_${label}`}
canDelete={canDelete}
>
<StyledColumnOption column={column} showType />
</OptionWrapper>
column={column}
/>
)),
[
canDelete,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
t,
} from '@superset-ui/core';
import { ColumnMeta } from '@superset-ui/chart-controls';
import { Tooltip } from 'src/components/Tooltip';
import {
OPERATOR_ENUM_TO_OPERATOR_TYPE,
Operators,
Expand Down Expand Up @@ -299,6 +298,7 @@ export const DndFilterSelect = (props: DndFilterSelectProps) => {
() =>
values.map((adhocFilter: AdhocFilter, index: number) => {
const label = adhocFilter.getDefaultLabel();
const tooltipTitle = adhocFilter.getTooltipTitle();
return (
<AdhocFilterPopoverTrigger
key={index}
Expand All @@ -311,14 +311,14 @@ export const DndFilterSelect = (props: DndFilterSelectProps) => {
<OptionWrapper
key={index}
index={index}
label={label}
tooltipTitle={tooltipTitle}
clickClose={onClickClose}
onShiftOptions={onShiftOptions}
type={DndItemType.FilterOption}
withCaret
isExtra={adhocFilter.isExtra}
>
<Tooltip title={label}>{label}</Tooltip>
</OptionWrapper>
/>
</AdhocFilterPopoverTrigger>
);
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ test('renders with default props', () => {
clickClose={jest.fn()}
type={'Column' as DndItemType}
onShiftOptions={jest.fn()}
>
Option
</OptionWrapper>,
label="Option"
/>,
{ useDnd: true },
);
expect(container).toBeInTheDocument();
Expand All @@ -46,17 +45,15 @@ test('triggers onShiftOptions on drop', () => {
clickClose={jest.fn()}
type={'Column' as DndItemType}
onShiftOptions={onShiftOptions}
>
Option 1
</OptionWrapper>
label="Option 1"
/>
<OptionWrapper
index={2}
clickClose={jest.fn()}
type={'Column' as DndItemType}
onShiftOptions={onShiftOptions}
>
Option 2
</OptionWrapper>
label="Option 2"
/>
</>,
{ useDnd: true },
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,19 @@ import {
OptionProps,
OptionItemInterface,
} from 'src/explore/components/controls/DndColumnSelectControl/types';
import { Tooltip } from 'src/components/Tooltip';
import { StyledColumnOption } from 'src/explore/components/optionRenderers';
import { styled } from '@superset-ui/core';
import { ColumnMeta } from '@superset-ui/chart-controls';
import Option from './Option';

export const OptionLabel = styled.div`
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;

export default function OptionWrapper(
props: OptionProps & {
type: string;
Expand All @@ -38,16 +49,19 @@ export default function OptionWrapper(
) {
const {
index,
label,
tooltipTitle,
column,
type,
onShiftOptions,
clickClose,
withCaret,
isExtra,
canDelete = true,
children,
...rest
} = props;
const ref = useRef<HTMLDivElement>(null);
const labelRef = useRef<HTMLDivElement>(null);

const item: OptionItemInterface = useMemo(
() => ({
Expand All @@ -56,7 +70,7 @@ export default function OptionWrapper(
}),
[index, type],
);
const [, drag] = useDrag({
const [{ isDragging }, drag] = useDrag({
item,
collect: (monitor: DragSourceMonitor) => ({
isDragging: monitor.isDragging(),
Expand Down Expand Up @@ -107,6 +121,51 @@ export default function OptionWrapper(
},
});

const shouldShowTooltip =
(!isDragging && tooltipTitle && label && tooltipTitle !== label) ||
(!isDragging &&
labelRef &&
labelRef.current &&
labelRef.current.scrollWidth > labelRef.current.clientWidth);

const LabelContent = () => {
if (!shouldShowTooltip) {
return <span>{label}</span>;
}
return (
<Tooltip title={tooltipTitle || label}>
<span>{label}</span>
</Tooltip>
);
};

const ColumnOption = () => (
<StyledColumnOption
column={column as ColumnMeta}
labelRef={labelRef}
showTooltip={!!shouldShowTooltip}
showType
/>
);

const Label = () => {
if (label) {
return (
<OptionLabel ref={labelRef}>
<LabelContent />
</OptionLabel>
);
}
if (column) {
return (
<OptionLabel>
<ColumnOption />
</OptionLabel>
);
}
return null;
};

drag(drop(ref));

return (
Expand All @@ -118,7 +177,7 @@ export default function OptionWrapper(
isExtra={isExtra}
canDelete={canDelete}
>
{children}
<Label />
</Option>
</DragContainer>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ import {
import { DndItemType } from '../../DndItemType';

export interface OptionProps {
children: ReactNode;
children?: ReactNode;
index: number;
label?: string;
tooltipTitle?: string;
column?: ColumnMeta;
clickClose: (index: number) => void;
withCaret?: boolean;
isExtra?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,10 @@ export const OptionControlContainer = styled.div<{
border-radius: 3px;
cursor: ${({ withCaret }) => (withCaret ? 'pointer' : 'default')};
`;

export const Label = styled.div`
${({ theme }) => `
display: flex;
max-width: 100%;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
align-items: center;
Expand All @@ -71,6 +70,11 @@ export const Label = styled.div`
`}
`;

const LabelText = styled.span`
overflow: hidden;
text-overflow: ellipsis;
`;

export const CaretContainer = styled.div`
height: 100%;
border-left: solid 1px ${({ theme }) => theme.colors.grayscale.dark2}0C;
Expand Down Expand Up @@ -197,6 +201,8 @@ export const OptionControlLabel = ({
}) => {
const theme = useTheme();
const ref = useRef<HTMLDivElement>(null);
const labelRef = useRef<HTMLDivElement>(null);
const hasMetricName = savedMetric?.metric_name;
const [, drop] = useDrop({
accept: type,
drop() {
Expand Down Expand Up @@ -250,7 +256,7 @@ export const OptionControlLabel = ({
item.index = hoverIndex;
},
});
const [, drag] = useDrag({
const [{ isDragging }, drag] = useDrag({
item: {
type,
index,
Expand All @@ -262,10 +268,34 @@ export const OptionControlLabel = ({
});

const getLabelContent = () => {
if (savedMetric?.metric_name) {
return <StyledMetricOption metric={savedMetric} />;
const shouldShowTooltip =
(!isDragging &&
typeof label === 'string' &&
tooltipTitle &&
label &&
tooltipTitle !== label) ||
(!isDragging &&
labelRef &&
labelRef.current &&
labelRef.current.scrollWidth > labelRef.current.clientWidth);

if (savedMetric && hasMetricName) {
return (
<StyledMetricOption
metric={savedMetric}
labelRef={labelRef}
showTooltip={!!shouldShowTooltip}
/>
);
}
if (!shouldShowTooltip) {
return <LabelText ref={labelRef}>{label}</LabelText>;
}
return <Tooltip title={tooltipTitle}>{label}</Tooltip>;
return (
<Tooltip title={tooltipTitle || label}>
<LabelText ref={labelRef}>{label}</LabelText>
</Tooltip>
);
};

const getOptionControlContent = () => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
} from '@superset-ui/chart-controls';

const OptionContainer = styled.div`
width: 100%;
> span {
display: flex;
align-items: center;
Expand Down

0 comments on commit a1e18ed

Please sign in to comment.