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

[XY, Pie] Long legend values support #108365

Merged
merged 7 commits into from
Aug 19, 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 @@ -16,3 +16,4 @@ export { RangeOption } from './range';
export { RequiredNumberInputOption } from './required_number_input';
export { TextInputOption } from './text_input';
export { PercentageModeOption } from './percentage_mode';
export { LongLegendOptions } from './long_legend_options';
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import { mountWithIntl } from '@kbn/test/jest';
import { LongLegendOptions, LongLegendOptionsProps } from './long_legend_options';
import { EuiFieldNumber } from '@elastic/eui';

describe('LongLegendOptions', () => {
let props: LongLegendOptionsProps;
let component;
beforeAll(() => {
props = {
truncateLegend: true,
setValue: jest.fn(),
};
});

it('renders the EuiFieldNumber', () => {
component = mountWithIntl(<LongLegendOptions {...props} />);
expect(component.find(EuiFieldNumber).length).toBe(1);
});

it('should call setValue when value is changes in the number input', () => {
component = mountWithIntl(<LongLegendOptions {...props} />);
const numberField = component.find(EuiFieldNumber);
numberField.props().onChange!(({
target: {
value: 3,
},
} as unknown) as React.ChangeEvent<HTMLInputElement>);

expect(props.setValue).toHaveBeenCalledWith('maxLegendLines', 3);
});

it('input number should be disabled when truncate is false', () => {
props.truncateLegend = false;
component = mountWithIntl(<LongLegendOptions {...props} />);
const numberField = component.find(EuiFieldNumber);

expect(numberField.props().disabled).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiFieldNumber, EuiFormRow } from '@elastic/eui';
import { SwitchOption } from './switch';

const MAX_TRUNCATE_LINES = 5;
const MIN_TRUNCATE_LINES = 1;

export interface LongLegendOptionsProps {
setValue: (paramName: 'maxLegendLines' | 'truncateLegend', value: boolean | number) => void;
truncateLegend: boolean;
maxLegendLines?: number;
'data-test-subj'?: string;
}

function LongLegendOptions({
'data-test-subj': dataTestSubj,
setValue,
truncateLegend,
maxLegendLines,
}: LongLegendOptionsProps) {
return (
<>
<SwitchOption
data-test-subj={dataTestSubj}
label={i18n.translate('visDefaultEditor.options.longLegends.truncateLegendTextLabel', {
defaultMessage: 'Truncate legend text',
})}
paramName="truncateLegend"
value={truncateLegend}
setValue={setValue}
/>
<EuiFormRow
fullWidth
label={
<FormattedMessage
id="visDefaultEditor.options.longLegends.maxLegendLinesLabel"
defaultMessage="Maximum legend lines"
/>
}
>
<EuiFieldNumber
data-test-subj="timeSeriesEditorDataMaxLegendLines"
value={maxLegendLines}
min={MIN_TRUNCATE_LINES}
max={MAX_TRUNCATE_LINES}
fullWidth
disabled={!Boolean(truncateLegend)}
onChange={(e) => {
const val = Number(e.target.value);
setValue(
'maxLegendLines',
Math.min(MAX_TRUNCATE_LINES, Math.max(val, MIN_TRUNCATE_LINES))
);
}}
/>
</EuiFormRow>
</>
);
}

export { LongLegendOptions };

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions src/plugins/vis_type_pie/public/editor/components/pie.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@ describe('PalettePicker', function () {
});
});

it('renders the long legend options for the elastic charts implementation', async () => {
component = mountWithIntl(<PieOptions {...props} />);
await act(async () => {
expect(findTestSubject(component, 'pieLongLegendsOptions').length).toBe(1);
});
});

it('not renders the long legend options for the vislib implementation', async () => {
component = mountWithIntl(<PieOptions {...props} showElasticChartsOptions={false} />);
await act(async () => {
expect(findTestSubject(component, 'pieLongLegendsOptions').length).toBe(0);
});
});

it('renders the label position dropdown for the elastic charts implementation', async () => {
component = mountWithIntl(<PieOptions {...props} />);
await act(async () => {
Expand Down
15 changes: 14 additions & 1 deletion src/plugins/vis_type_pie/public/editor/components/pie.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
SwitchOption,
SelectOption,
PalettePicker,
LongLegendOptions,
} from '../../../../vis_default_editor/public';
import { VisEditorOptionsProps } from '../../../../visualizations/public';
import { TruncateLabelsOption } from './truncate_labels';
Expand Down Expand Up @@ -169,6 +170,12 @@ const PieOptions = (props: PieOptionsProps) => {
}}
data-test-subj="visTypePieNestedLegendSwitch"
/>
<LongLegendOptions
data-test-subj="pieLongLegendsOptions"
truncateLegend={stateParams.truncateLegend ?? true}
maxLegendLines={stateParams.maxLegendLines ?? 1}
setValue={setValue}
/>
</>
)}
{props.showElasticChartsOptions && palettesRegistry && (
Expand Down Expand Up @@ -276,7 +283,13 @@ const PieOptions = (props: PieOptionsProps) => {
/>
</>
)}
<TruncateLabelsOption value={stateParams.labels.truncate} setValue={setLabels} />
<TruncateLabelsOption
value={stateParams.labels.truncate}
setValue={setLabels}
disabled={
props.showElasticChartsOptions && stateParams.labels.position === LabelPositions.INSIDE
}
/>
</EuiPanel>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import React, { ChangeEvent } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiFormRow, EuiFieldNumber } from '@elastic/eui';
import { EuiFormRow, EuiFieldNumber, EuiIconTip } from '@elastic/eui';

export interface TruncateLabelsOptionProps {
disabled?: boolean;
Expand All @@ -27,6 +27,16 @@ function TruncateLabelsOption({ disabled, value = null, setValue }: TruncateLabe
})}
fullWidth
display="rowCompressed"
labelAppend={
<EuiIconTip
content={i18n.translate('visTypePie.controls.truncateTooltip', {
defaultMessage: 'Number of characters for labels positioned outside the chart.',
})}
position="top"
type="iInCircle"
color="subdued"
/>
}
>
<EuiFieldNumber
data-test-subj="pieLabelTruncateInput"
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/vis_type_pie/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ export const createMockPieParams = (): PieVisParams => {
},
legendPosition: 'right',
nestedLegend: false,
maxLegendLines: 1,
truncateLegend: true,
distinctColors: false,
palette: {
name: 'default',
Expand Down
11 changes: 10 additions & 1 deletion src/plugins/vis_type_pie/public/pie_component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,16 @@ const PieComponent = (props: PieComponentProps) => {
services.actions,
services.fieldFormats
)}
theme={chartTheme}
theme={[
chartTheme,
{
legend: {
labelOptions: {
maxLines: visParams.truncateLegend ? visParams.maxLegendLines ?? 1 : 0,
},
},
},
]}
baseTheme={chartBaseTheme}
onRenderChange={onRenderChange}
/>
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/vis_type_pie/public/pie_fn.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ describe('interpreter/functions#pie', () => {
legendPosition: 'right',
isDonut: true,
nestedLegend: true,
truncateLegend: true,
maxLegendLines: true,
distinctColors: false,
palette: 'kibana_palette',
labels: {
Expand Down
13 changes: 13 additions & 0 deletions src/plugins/vis_type_pie/public/pie_fn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ export const createPieVisFn = (): VisTypePieExpressionFunctionDefinition => ({
}),
default: false,
},
truncateLegend: {
types: ['boolean'],
help: i18n.translate('visTypePie.function.args.truncateLegendHelpText', {
defaultMessage: 'Defines if the legend items will be truncated or not',
}),
default: true,
},
maxLegendLines: {
types: ['number'],
help: i18n.translate('visTypePie.function.args.maxLegendLinesHelpText', {
defaultMessage: 'Defines the number of lines per legend item',
}),
},
distinctColors: {
types: ['boolean'],
help: i18n.translate('visTypePie.function.args.distinctColorsHelpText', {
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/vis_type_pie/public/sample_vis.test.mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export const samplePieVis = {
legendPosition: 'right',
isDonut: true,
nestedLegend: true,
truncateLegend: true,
maxLegendLines: 1,
distinctColors: false,
palette: 'kibana_palette',
labels: {
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/vis_type_pie/public/to_ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export const toExpressionAst: VisToExpressionAst<PieVisParams> = async (vis, par
addLegend: vis.params.addLegend,
legendPosition: vis.params.legendPosition,
nestedLegend: vis.params?.nestedLegend,
truncateLegend: vis.params.truncateLegend,
maxLegendLines: vis.params.maxLegendLines,
distinctColors: vis.params?.distinctColors,
isDonut: vis.params.isDonut,
palette: vis.params?.palette?.name,
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/vis_type_pie/public/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ interface PieCommonParams {
addLegend: boolean;
legendPosition: Position;
nestedLegend: boolean;
truncateLegend: boolean;
maxLegendLines: number;
distinctColors: boolean;
isDonut: boolean;
}
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/vis_type_pie/public/utils/get_columns.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ describe('getColumns', () => {
},
legendPosition: 'right',
nestedLegend: false,
maxLegendLines: 1,
truncateLegend: false,
palette: {
name: 'default',
type: 'palette',
Expand Down
1 change: 1 addition & 0 deletions src/plugins/vis_type_pie/public/utils/get_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export const getConfig = (
config.linkLabel = {
maxCount: Number.POSITIVE_INFINITY,
maximumSection: Number.POSITIVE_INFINITY,
maxTextLength: visParams.labels.truncate ?? undefined,
};
}

Expand Down
7 changes: 1 addition & 6 deletions src/plugins/vis_type_pie/public/utils/get_layers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,7 @@ export const getLayers = (
showAccessor: (d: Datum) => d !== EMPTY_SLICE,
nodeLabel: (d: unknown) => {
if (col.format) {
const formattedLabel = formatter.deserialize(col.format).convert(d) ?? '';
if (visParams.labels.truncate && formattedLabel.length <= visParams.labels.truncate) {
return formattedLabel;
} else {
return `${formattedLabel.slice(0, Number(visParams.labels.truncate))}\u2026`;
}
return formatter.deserialize(col.format).convert(d) ?? '';
}
return String(d);
},
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/vis_type_pie/public/vis_type/pie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export const getPieVisTypeDefinition = ({
addLegend: !showElasticChartsOptions,
legendPosition: Position.Right,
nestedLegend: false,
truncateLegend: true,
maxLegendLines: 1,
distinctColors: false,
isDonut: true,
palette: {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading