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

[7.x] [Lens] Add search to chart switcher (#77631) #79709

Merged
merged 1 commit into from
Oct 6, 2020
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 @@ -16,3 +16,7 @@ img.lnsChartSwitch__chartIcon { // sass-lint:disable-line no-qualifying-elements
// The large icons aren't square so max out the width to fill the height
width: 100%;
}

.lnsChartSwitch__search {
width: 4 * $euiSizeXXL;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ import {
EuiPopoverTitle,
EuiKeyPadMenu,
EuiKeyPadMenuItem,
EuiFieldSearch,
EuiFlexGroup,
EuiFlexItem,
EuiSelectableMessage,
} from '@elastic/eui';
import { flatten } from 'lodash';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { Visualization, FramePublicAPI, Datasource } from '../../../types';
import { Action } from '../state_management';
import { getSuggestions, switchToSuggestion, Suggestion } from '../suggestion_helpers';
Expand Down Expand Up @@ -173,6 +178,8 @@ export function ChartSwitch(props: Props) {
};
}

const [searchTerm, setSearchTerm] = useState('');

const visualizationTypes = useMemo(
() =>
flyoutOpen &&
Expand All @@ -184,17 +191,25 @@ export function ChartSwitch(props: Props) {
icon: t.icon,
}))
)
).map((visualizationType) => ({
...visualizationType,
selection: getSelection(visualizationType.visualizationId, visualizationType.id),
})),
)
.filter(
(visualizationType) =>
visualizationType.label.toLowerCase().includes(searchTerm.toLowerCase()) ||
(visualizationType.fullLabel &&
visualizationType.fullLabel.toLowerCase().includes(searchTerm.toLowerCase()))
)
.map((visualizationType) => ({
...visualizationType,
selection: getSelection(visualizationType.visualizationId, visualizationType.id),
})),
// eslint-disable-next-line react-hooks/exhaustive-deps
[
flyoutOpen,
props.visualizationMap,
props.framePublicAPI,
props.visualizationId,
props.visualizationState,
searchTerm,
]
);

Expand All @@ -219,15 +234,30 @@ export function ChartSwitch(props: Props) {
anchorPosition="downLeft"
>
<EuiPopoverTitle>
{i18n.translate('xpack.lens.configPanel.selectVisualization', {
defaultMessage: 'Select a visualization',
})}
<EuiFlexGroup alignItems="center" responsive={false}>
<EuiFlexItem>
{i18n.translate('xpack.lens.configPanel.chartType', {
defaultMessage: 'Chart type',
})}
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFieldSearch
compressed
fullWidth={false}
className="lnsChartSwitch__search"
value={searchTerm}
data-test-subj="lnsChartSwitchSearch"
onChange={(e) => setSearchTerm(e.target.value)}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPopoverTitle>
<EuiKeyPadMenu>
{(visualizationTypes || []).map((v) => (
<EuiKeyPadMenuItem
key={`${v.visualizationId}:${v.id}`}
label={<span data-test-subj="visTypeTitle">{v.label}</span>}
title={v.fullLabel}
role="menuitem"
data-test-subj={`lnsChartSwitchPopover_${v.id}`}
onClick={() => commitSelection(v.selection)}
Expand All @@ -251,6 +281,17 @@ export function ChartSwitch(props: Props) {
</EuiKeyPadMenuItem>
))}
</EuiKeyPadMenu>
{searchTerm && (visualizationTypes || []).length === 0 && (
<EuiSelectableMessage>
<FormattedMessage
id="xpack.lens.chartSwitch.noResults"
defaultMessage="No results found for {term}."
values={{
term: <strong>{searchTerm}</strong>,
}}
/>
</EuiSelectableMessage>
)}
</EuiPopover>
);

Expand Down
16 changes: 16 additions & 0 deletions x-pack/plugins/lens/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,10 +430,26 @@ export interface FramePublicAPI {
removeLayers: (layerIds: string[]) => void;
}

/**
* A visualization type advertised to the user in the chart switcher
*/
export interface VisualizationType {
/**
* Unique id of the visualization type within the visualization defining it
*/
id: string;
/**
* Icon used in the chart switcher
*/
icon: IconType;
/**
* Visible label used in the chart switcher and above the workspace panel in collapsed state
*/
label: string;
/**
* Optional label used in chart type search if chart switcher is expanded and for tooltips
*/
fullLabel?: string;
}

export interface Visualization<T = unknown> {
Expand Down
20 changes: 16 additions & 4 deletions x-pack/plugins/lens/public/xy_visualization/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,9 @@ export const visualizationTypes: VisualizationType[] = [
id: 'bar_horizontal',
icon: LensIconChartBarHorizontal,
label: i18n.translate('xpack.lens.xyVisualization.barHorizontalLabel', {
defaultMessage: 'H. Bar',
}),
fullLabel: i18n.translate('xpack.lens.xyVisualization.barHorizontalFullLabel', {
defaultMessage: 'Horizontal bar',
}),
},
Expand All @@ -440,22 +443,31 @@ export const visualizationTypes: VisualizationType[] = [
id: 'bar_percentage_stacked',
icon: LensIconChartBarPercentage,
label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageBarLabel', {
defaultMessage: 'Bar percentage',
defaultMessage: 'Percentage bar',
}),
},
{
id: 'bar_horizontal_stacked',
icon: LensIconChartBarHorizontalStacked,
label: i18n.translate('xpack.lens.xyVisualization.stackedBarHorizontalLabel', {
defaultMessage: 'Stacked horizontal bar',
defaultMessage: 'H. Stacked bar',
}),
fullLabel: i18n.translate('xpack.lens.xyVisualization.stackedBarHorizontalFullLabel', {
defaultMessage: 'Horizontal stacked bar',
}),
},
{
id: 'bar_horizontal_percentage_stacked',
icon: LensIconChartBarHorizontalPercentage,
label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageBarHorizontalLabel', {
defaultMessage: 'Horizontal bar percentage',
defaultMessage: 'H. Percentage bar',
}),
fullLabel: i18n.translate(
'xpack.lens.xyVisualization.stackedPercentageBarHorizontalFullLabel',
{
defaultMessage: 'Horizontal percentage bar',
}
),
},
{
id: 'area',
Expand All @@ -475,7 +487,7 @@ export const visualizationTypes: VisualizationType[] = [
id: 'area_percentage_stacked',
icon: LensIconChartAreaPercentage,
label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageAreaLabel', {
defaultMessage: 'Area percentage',
defaultMessage: 'Percentage area',
}),
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,38 +44,38 @@ describe('xy_visualization', () => {
it('should show mixed xy chart when multilple series types', () => {
const desc = xyVisualization.getDescription(mixedState('bar', 'line'));

expect(desc.label).toEqual('Mixed XY chart');
expect(desc.label).toEqual('Mixed XY');
});

it('should show the preferredSeriesType if there are no layers', () => {
const desc = xyVisualization.getDescription(mixedState());

expect(desc.icon).toEqual(LensIconChartBar);
expect(desc.label).toEqual('Bar chart');
expect(desc.label).toEqual('Bar');
});

it('should show mixed horizontal bar chart when multiple horizontal bar types', () => {
const desc = xyVisualization.getDescription(
mixedState('bar_horizontal', 'bar_horizontal_stacked')
);

expect(desc.label).toEqual('Mixed horizontal bar chart');
expect(desc.label).toEqual('Mixed H. bar');
});

it('should show bar chart when bar only', () => {
const desc = xyVisualization.getDescription(mixedState('bar_horizontal', 'bar_horizontal'));

expect(desc.label).toEqual('Horizontal bar chart');
expect(desc.label).toEqual('H. Bar');
});

it('should show the chart description if not mixed', () => {
expect(xyVisualization.getDescription(mixedState('area')).label).toEqual('Area chart');
expect(xyVisualization.getDescription(mixedState('line')).label).toEqual('Line chart');
expect(xyVisualization.getDescription(mixedState('area')).label).toEqual('Area');
expect(xyVisualization.getDescription(mixedState('line')).label).toEqual('Line');
expect(xyVisualization.getDescription(mixedState('area_stacked')).label).toEqual(
'Stacked area chart'
'Stacked area'
);
expect(xyVisualization.getDescription(mixedState('bar_horizontal_stacked')).label).toEqual(
'Stacked horizontal bar chart'
'H. Stacked bar'
);
});
});
Expand Down
8 changes: 2 additions & 6 deletions x-pack/plugins/lens/public/xy_visualization/visualization.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function getDescription(state?: State) {
return {
icon: LensIconChartBarHorizontal,
label: i18n.translate('xpack.lens.xyVisualization.mixedBarHorizontalLabel', {
defaultMessage: 'Mixed horizontal bar',
defaultMessage: 'Mixed H. bar',
}),
};
}
Expand Down Expand Up @@ -118,14 +118,10 @@ export const xyVisualization: Visualization<State> = {

getDescription(state) {
const { icon, label } = getDescription(state);
const chartLabel = i18n.translate('xpack.lens.xyVisualization.chartLabel', {
defaultMessage: '{label} chart',
values: { label },
});

return {
icon: icon || defaultIcon,
label: chartLabel,
label,
};
},

Expand Down
3 changes: 0 additions & 3 deletions x-pack/plugins/translations/translations/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -9659,15 +9659,12 @@
"xpack.lens.xySuggestions.unstackedChartTitle": "スタックが解除されました",
"xpack.lens.xySuggestions.yAxixConjunctionSign": " と ",
"xpack.lens.xyVisualization.areaLabel": "エリア",
"xpack.lens.xyVisualization.barHorizontalLabel": "横棒",
"xpack.lens.xyVisualization.barLabel": "バー",
"xpack.lens.xyVisualization.chartLabel": "{label} チャート",
"xpack.lens.xyVisualization.lineLabel": "折れ線",
"xpack.lens.xyVisualization.mixedBarHorizontalLabel": "ミックスされた横棒",
"xpack.lens.xyVisualization.mixedLabel": "ミックスされた XY",
"xpack.lens.xyVisualization.noDataLabel": "結果が見つかりませんでした",
"xpack.lens.xyVisualization.stackedAreaLabel": "スタックされたエリア",
"xpack.lens.xyVisualization.stackedBarHorizontalLabel": "スタックされた横棒",
"xpack.lens.xyVisualization.stackedBarLabel": "スタックされたバー",
"xpack.lens.xyVisualization.xyLabel": "XY",
"xpack.licenseMgmt.app.checkingPermissionsErrorMessage": "パーミッションの確認中にエラーが発生",
Expand Down
3 changes: 0 additions & 3 deletions x-pack/plugins/translations/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -9665,15 +9665,12 @@
"xpack.lens.xySuggestions.unstackedChartTitle": "非堆叠",
"xpack.lens.xySuggestions.yAxixConjunctionSign": " &amp; ",
"xpack.lens.xyVisualization.areaLabel": "面积图",
"xpack.lens.xyVisualization.barHorizontalLabel": "水平条形图",
"xpack.lens.xyVisualization.barLabel": "条形图",
"xpack.lens.xyVisualization.chartLabel": "{label} 图表",
"xpack.lens.xyVisualization.lineLabel": "折线图",
"xpack.lens.xyVisualization.mixedBarHorizontalLabel": "混合水平条形图",
"xpack.lens.xyVisualization.mixedLabel": "混合 XY",
"xpack.lens.xyVisualization.noDataLabel": "找不到结果",
"xpack.lens.xyVisualization.stackedAreaLabel": "堆叠面积图",
"xpack.lens.xyVisualization.stackedBarHorizontalLabel": "堆叠水平条形图",
"xpack.lens.xyVisualization.stackedBarLabel": "堆叠条形图",
"xpack.lens.xyVisualization.xyLabel": "XY",
"xpack.licenseMgmt.app.checkingPermissionsErrorMessage": "检查权限时出错",
Expand Down