[Lens] Fix axis title visibility bug (#134082)

* 🐛 fix title visibility bug

* 🏷️ Fix type issues
This commit is contained in:
Marco Liberati 2022-06-15 16:00:26 +02:00 committed by GitHub
parent 32eb974887
commit 342e7a1783
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 92 additions and 86 deletions

View file

@ -287,7 +287,7 @@ export function XYChart({
const getYAxesTitles = (axisSeries: Series[]) => {
return axisSeries
.map(({ layer, accessor }) => titles?.[layer]?.yTitles?.[accessor])
.filter((name) => Boolean(name))[0];
.find((name) => Boolean(name));
};
const referenceLineLayers = getReferenceLayers(layers);

View file

@ -154,19 +154,17 @@ export const HeatmapToolbar = memo(
<AxisTitleSettings
axis="yLeft"
axisTitle={state?.gridConfig.yTitle}
updateTitleState={(value) =>
updateTitleState={({ title, visible }) => {
setState({
...state,
gridConfig: { ...state.gridConfig, yTitle: value },
})
}
gridConfig: {
...state.gridConfig,
yTitle: title,
isYAxisTitleVisible: visible,
},
});
}}
isAxisTitleVisible={state?.gridConfig.isYAxisTitleVisible}
toggleAxisTitleVisibility={(_, checked) =>
setState({
...state,
gridConfig: { ...state.gridConfig, isYAxisTitleVisible: checked },
})
}
/>
</ToolbarPopover>
</TooltipWrapper>
@ -189,19 +187,17 @@ export const HeatmapToolbar = memo(
<AxisTitleSettings
axis="x"
axisTitle={state?.gridConfig.xTitle}
updateTitleState={(value) =>
updateTitleState={({ title, visible }) =>
setState({
...state,
gridConfig: { ...state.gridConfig, xTitle: value },
gridConfig: {
...state.gridConfig,
xTitle: title,
isXAxisTitleVisible: visible,
},
})
}
isAxisTitleVisible={state?.gridConfig.isXAxisTitleVisible}
toggleAxisTitleVisibility={(_, checked) =>
setState({
...state,
gridConfig: { ...state.gridConfig, isXAxisTitleVisible: checked },
})
}
/>
</ToolbarPopover>
</TooltipWrapper>

View file

@ -18,7 +18,6 @@ describe('Axes Title settings', () => {
axisTitle: 'My custom X axis title',
axis: 'x',
isAxisTitleVisible: true,
toggleAxisTitleVisibility: jest.fn(),
updateTitleState: jest.fn(),
};
});
@ -39,6 +38,15 @@ describe('Axes Title settings', () => {
expect(component.find('[data-test-subj="lnsxAxisTitle"]').last().prop('value')).toBe('');
});
it('should set the mode to None if empty title is passed over and the visibility is set to false', () => {
const component = mount(
<AxisTitleSettings {...props} axisTitle={''} isAxisTitleVisible={false} />
);
expect(component.find('[data-test-subj="lnsxAxisTitle-select"]').last().prop('value')).toBe(
'none'
);
});
it('should disable the input text if the switch is off', () => {
const component = mount(<AxisTitleSettings {...props} isAxisTitleVisible={false} />);
expect(component.find('[data-test-subj="lnsxAxisTitle"]').last().prop('disabled')).toBe(true);

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { useCallback, useState } from 'react';
import React, { useCallback, useMemo } from 'react';
import { EuiSpacer, EuiFormRow } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { AxesSettingsConfig } from '@kbn/expression-xy-plugin/common';
@ -23,17 +23,16 @@ export interface AxisTitleSettingsProps {
*/
axisTitle: string | undefined;
/**
* Callback to axis title change
* Callback to axis title change for both title and visibility
*/
updateTitleState: (value: string) => void;
updateTitleState: (
state: { title?: string; visible: boolean },
axis: AxesSettingsConfigKeys
) => void;
/**
* Determines if the title visibility switch is on and the input text is disabled
*/
isAxisTitleVisible: boolean;
/**
* Toggles the axis title visibility
*/
toggleAxisTitleVisibility: (axis: AxesSettingsConfigKeys, checked: boolean) => void;
}
export const AxisTitleSettings: React.FunctionComponent<AxisTitleSettingsProps> = ({
@ -41,29 +40,34 @@ export const AxisTitleSettings: React.FunctionComponent<AxisTitleSettingsProps>
axisTitle,
updateTitleState,
isAxisTitleVisible,
toggleAxisTitleVisibility,
}) => {
const { inputValue: title, handleInputChange: onTitleChange } = useDebouncedValue<string>(
const axisState = useMemo(
() => ({
title: axisTitle,
visibility:
!axisTitle && isAxisTitleVisible
? 'auto'
: isAxisTitleVisible
? 'custom'
: ('none' as LabelMode),
}),
[axisTitle, isAxisTitleVisible]
);
const onTitleChange = useCallback(
({ title, visibility }: { title?: string; visibility: LabelMode }) =>
updateTitleState({ title, visible: visibility !== 'none' }, axis),
[axis, updateTitleState]
);
const { inputValue: localAxisState, handleInputChange: onLocalTitleChange } = useDebouncedValue<{
title?: string;
visibility: LabelMode;
}>(
{
value: axisTitle || '',
onChange: updateTitleState,
value: axisState,
onChange: onTitleChange,
},
{ allowFalsyValue: true }
);
const [titleMode, setTitleMode] = useState<LabelMode>(
!title ? 'auto' : isAxisTitleVisible ? 'custom' : 'none'
);
const updateVisibility = useCallback(
(mode: LabelMode) => {
const visible = mode !== 'none';
if (visible !== isAxisTitleVisible) {
toggleAxisTitleVisibility(axis, visible);
}
setTitleMode(mode);
},
[axis, isAxisTitleVisible, toggleAxisTitleVisibility]
);
return (
<>
@ -79,17 +83,14 @@ export const AxisTitleSettings: React.FunctionComponent<AxisTitleSettingsProps>
defaultMessage: 'Axis title',
})}
dataTestSubj={`lns${axis}AxisTitle`}
label={title || ''}
mode={titleMode}
label={localAxisState.title || ''}
mode={localAxisState.visibility}
placeholder={i18n.translate('xpack.lens.shared.overwriteAxisTitle', {
defaultMessage: 'Overwrite axis title',
})}
hasAutoOption={true}
handleChange={({ mode, label }) => {
if (title !== label) {
onTitleChange(label);
}
updateVisibility(mode);
onLocalTitleChange({ title: label, visibility: mode });
}}
/>
</EuiFormRow>

View file

@ -42,7 +42,6 @@ describe('Axes Settings', () => {
areTickLabelsVisible: true,
areGridlinesVisible: true,
isAxisTitleVisible: true,
toggleAxisTitleVisibility: jest.fn(),
toggleTickLabelsVisibility: jest.fn(),
toggleGridlinesVisibility: jest.fn(),
hasBarOrAreaOnAxis: false,

View file

@ -53,7 +53,10 @@ export interface AxisSettingsPopoverProps {
/**
* Callback to axis title change
*/
updateTitleState: (value: string) => void;
updateTitleState: (
title: { title?: string; visible: boolean },
axis: AxesSettingsConfigKeys
) => void;
/**
* Determines if the popover is Disabled
*/
@ -86,10 +89,6 @@ export interface AxisSettingsPopoverProps {
* Determines if the title visibility switch is on and the input text is disabled
*/
isAxisTitleVisible: boolean;
/**
* Toggles the axis title visibility
*/
toggleAxisTitleVisibility: (axis: AxesSettingsConfigKeys, checked: boolean) => void;
/**
* Set endzone visibility
*/
@ -219,7 +218,6 @@ export const AxisSettingsPopover: React.FunctionComponent<AxisSettingsPopoverPro
isAxisTitleVisible,
orientation,
setOrientation,
toggleAxisTitleVisibility,
setEndzoneVisibility,
endzonesVisible,
extent,
@ -271,7 +269,6 @@ export const AxisSettingsPopover: React.FunctionComponent<AxisSettingsPopoverPro
axisTitle={axisTitle}
updateTitleState={updateTitleState}
isAxisTitleVisible={isAxisTitleVisible}
toggleAxisTitleVisibility={toggleAxisTitleVisibility}
/>
<EuiFormRow
display="columnCompressedSwitch"

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { memo, useCallback, useState } from 'react';
import React, { memo, useCallback, useMemo, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { Position, ScaleType } from '@elastic/charts';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
@ -113,6 +113,13 @@ function hasPercentageAxis(axisGroups: GroupsConfiguration, groupId: string, sta
);
}
const axisKeyToTitleMapping: Record<keyof AxesSettingsConfig, 'xTitle' | 'yTitle' | 'yRightTitle'> =
{
x: 'xTitle',
yLeft: 'yTitle',
yRight: 'yRightTitle',
};
export const XyToolbar = memo(function XyToolbar(
props: VisualizationToolbarProps<State> & { useLegacyTimeAxis?: boolean }
) {
@ -180,27 +187,28 @@ export const XyToolbar = memo(function XyToolbar(
});
};
const axisTitlesVisibilitySettings = {
x: state?.axisTitlesVisibilitySettings?.x ?? true,
yLeft: state?.axisTitlesVisibilitySettings?.yLeft ?? true,
yRight: state?.axisTitlesVisibilitySettings?.yRight ?? true,
};
const onAxisTitlesVisibilitySettingsChange = (
axis: AxesSettingsConfigKeys,
checked: boolean
): void => {
const newAxisTitlesVisibilitySettings = {
...axisTitlesVisibilitySettings,
...{
[axis]: checked,
},
};
setState({
...state,
axisTitlesVisibilitySettings: newAxisTitlesVisibilitySettings,
});
};
const axisTitlesVisibilitySettings = useMemo(
() => ({
x: state?.axisTitlesVisibilitySettings?.x ?? true,
yLeft: state?.axisTitlesVisibilitySettings?.yLeft ?? true,
yRight: state?.axisTitlesVisibilitySettings?.yRight ?? true,
}),
[
state?.axisTitlesVisibilitySettings?.x,
state?.axisTitlesVisibilitySettings?.yLeft,
state?.axisTitlesVisibilitySettings?.yRight,
]
);
const onTitleStateChange = useCallback(
({ title, visible }: { title?: string; visible: boolean }, axis: keyof AxesSettingsConfig) =>
setState({
...state,
[axisKeyToTitleMapping[axis]]: title,
axisTitlesVisibilitySettings: { ...axisTitlesVisibilitySettings, [axis]: visible },
}),
[axisTitlesVisibilitySettings, setState, state]
);
const nonOrdinalXAxis = dataLayers.every(
(layer) =>
!layer.xAccessor ||
@ -452,7 +460,7 @@ export const XyToolbar = memo(function XyToolbar(
axis="yLeft"
layers={state?.layers}
axisTitle={state?.yTitle}
updateTitleState={(value) => setState({ ...state, yTitle: value })}
updateTitleState={onTitleStateChange}
areTickLabelsVisible={tickLabelsVisibilitySettings.yLeft}
toggleTickLabelsVisibility={onTickLabelsVisibilitySettingsChange}
areGridlinesVisible={gridlinesVisibilitySettings.yLeft}
@ -463,7 +471,6 @@ export const XyToolbar = memo(function XyToolbar(
orientation={labelsOrientation.yLeft}
setOrientation={onLabelsOrientationChange}
isAxisTitleVisible={axisTitlesVisibilitySettings.yLeft}
toggleAxisTitleVisibility={onAxisTitlesVisibilitySettingsChange}
extent={state?.yLeftExtent || { mode: 'full' }}
setExtent={setLeftExtent}
hasBarOrAreaOnAxis={hasBarOrAreaOnLeftAxis}
@ -483,7 +490,7 @@ export const XyToolbar = memo(function XyToolbar(
axis="x"
layers={state?.layers}
axisTitle={state?.xTitle}
updateTitleState={(value) => setState({ ...state, xTitle: value })}
updateTitleState={onTitleStateChange}
areTickLabelsVisible={tickLabelsVisibilitySettings.x}
toggleTickLabelsVisibility={onTickLabelsVisibilitySettingsChange}
areGridlinesVisible={gridlinesVisibilitySettings.x}
@ -491,7 +498,6 @@ export const XyToolbar = memo(function XyToolbar(
orientation={labelsOrientation.x}
setOrientation={onLabelsOrientationChange}
isAxisTitleVisible={axisTitlesVisibilitySettings.x}
toggleAxisTitleVisibility={onAxisTitlesVisibilitySettingsChange}
endzonesVisible={!state?.hideEndzones}
setEndzoneVisibility={onChangeEndzoneVisiblity}
hasBarOrAreaOnAxis={false}
@ -522,7 +528,7 @@ export const XyToolbar = memo(function XyToolbar(
axis="yRight"
layers={state?.layers}
axisTitle={state?.yRightTitle}
updateTitleState={(value) => setState({ ...state, yRightTitle: value })}
updateTitleState={onTitleStateChange}
areTickLabelsVisible={tickLabelsVisibilitySettings.yRight}
toggleTickLabelsVisibility={onTickLabelsVisibilitySettingsChange}
areGridlinesVisible={gridlinesVisibilitySettings.yRight}
@ -535,7 +541,6 @@ export const XyToolbar = memo(function XyToolbar(
setOrientation={onLabelsOrientationChange}
hasPercentageAxis={hasPercentageAxis(axisGroups, 'right', state)}
isAxisTitleVisible={axisTitlesVisibilitySettings.yRight}
toggleAxisTitleVisibility={onAxisTitlesVisibilitySettingsChange}
extent={state?.yRightExtent || { mode: 'full' }}
setExtent={setRightExtent}
hasBarOrAreaOnAxis={hasBarOrAreaOnRightAxis}