kibana/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx
Marco Liberati e9e7453e1d
[Lens] Improves error messages when in Dashboard (#90668)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
2021-02-15 13:00:31 +01:00

271 lines
7.3 KiB
TypeScript

/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import './toolbar.scss';
import React, { useState } from 'react';
import useDebounce from 'react-use/lib/useDebounce';
import { i18n } from '@kbn/i18n';
import {
EuiFlexGroup,
EuiFormRow,
EuiSuperSelect,
EuiRange,
EuiHorizontalRule,
} from '@elastic/eui';
import { Position } from '@elastic/charts';
import { PaletteRegistry } from 'src/plugins/charts/public';
import { DEFAULT_PERCENT_DECIMALS } from './constants';
import { PieVisualizationState, SharedPieLayerState } from './types';
import { VisualizationDimensionEditorProps, VisualizationToolbarProps } from '../types';
import { ToolbarPopover, LegendSettingsPopover } from '../shared_components';
import { PalettePicker } from '../shared_components';
const numberOptions: Array<{
value: SharedPieLayerState['numberDisplay'];
inputDisplay: string;
}> = [
{
value: 'hidden',
inputDisplay: i18n.translate('xpack.lens.pieChart.hiddenNumbersLabel', {
defaultMessage: 'Hide from chart',
}),
},
{
value: 'percent',
inputDisplay: i18n.translate('xpack.lens.pieChart.showPercentValuesLabel', {
defaultMessage: 'Show percent',
}),
},
{
value: 'value',
inputDisplay: i18n.translate('xpack.lens.pieChart.showFormatterValuesLabel', {
defaultMessage: 'Show value',
}),
},
];
const categoryOptions: Array<{
value: SharedPieLayerState['categoryDisplay'];
inputDisplay: string;
}> = [
{
value: 'default',
inputDisplay: i18n.translate('xpack.lens.pieChart.showCategoriesLabel', {
defaultMessage: 'Inside or outside',
}),
},
{
value: 'inside',
inputDisplay: i18n.translate('xpack.lens.pieChart.fitInsideOnlyLabel', {
defaultMessage: 'Inside only',
}),
},
{
value: 'hide',
inputDisplay: i18n.translate('xpack.lens.pieChart.categoriesInLegendLabel', {
defaultMessage: 'Hide labels',
}),
},
];
const categoryOptionsTreemap: Array<{
value: SharedPieLayerState['categoryDisplay'];
inputDisplay: string;
}> = [
{
value: 'default',
inputDisplay: i18n.translate('xpack.lens.pieChart.showTreemapCategoriesLabel', {
defaultMessage: 'Show labels',
}),
},
{
value: 'hide',
inputDisplay: i18n.translate('xpack.lens.pieChart.categoriesInLegendLabel', {
defaultMessage: 'Hide labels',
}),
},
];
const legendOptions: Array<{
value: SharedPieLayerState['legendDisplay'];
label: string;
id: string;
}> = [
{
id: 'pieLegendDisplay-default',
value: 'default',
label: i18n.translate('xpack.lens.pieChart.legendVisibility.auto', {
defaultMessage: 'Auto',
}),
},
{
id: 'pieLegendDisplay-show',
value: 'show',
label: i18n.translate('xpack.lens.pieChart.legendVisibility.show', {
defaultMessage: 'Show',
}),
},
{
id: 'pieLegendDisplay-hide',
value: 'hide',
label: i18n.translate('xpack.lens.pieChart.legendVisibility.hide', {
defaultMessage: 'Hide',
}),
},
];
export function PieToolbar(props: VisualizationToolbarProps<PieVisualizationState>) {
const { state, setState } = props;
const layer = state.layers[0];
if (!layer) {
return null;
}
return (
<EuiFlexGroup gutterSize="none" justifyContent="spaceBetween">
<ToolbarPopover
title={i18n.translate('xpack.lens.pieChart.valuesLabel', {
defaultMessage: 'Labels',
})}
type="labels"
groupPosition="left"
buttonDataTestSubj="lnsLabelsButton"
>
<EuiFormRow
label={i18n.translate('xpack.lens.pieChart.labelPositionLabel', {
defaultMessage: 'Position',
})}
fullWidth
display="columnCompressed"
>
<EuiSuperSelect
compressed
valueOfSelected={layer.categoryDisplay}
options={state.shape === 'treemap' ? categoryOptionsTreemap : categoryOptions}
onChange={(option) => {
setState({
...state,
layers: [{ ...layer, categoryDisplay: option }],
});
}}
/>
</EuiFormRow>
<EuiFormRow
label={i18n.translate('xpack.lens.pieChart.numberLabels', {
defaultMessage: 'Values',
})}
fullWidth
display="columnCompressed"
>
<EuiSuperSelect
compressed
disabled={layer.categoryDisplay === 'hide'}
valueOfSelected={layer.categoryDisplay === 'hide' ? 'hidden' : layer.numberDisplay}
options={numberOptions}
onChange={(option) => {
setState({
...state,
layers: [{ ...layer, numberDisplay: option }],
});
}}
/>
</EuiFormRow>
<EuiHorizontalRule margin="s" />
<EuiFormRow
label={i18n.translate('xpack.lens.pieChart.percentDecimalsLabel', {
defaultMessage: 'Maximum decimal places for percent',
})}
fullWidth
display="rowCompressed"
>
<DecimalPlaceSlider
value={layer.percentDecimals ?? DEFAULT_PERCENT_DECIMALS}
setValue={(value) =>
setState({
...state,
layers: [{ ...layer, percentDecimals: value }],
})
}
/>
</EuiFormRow>
</ToolbarPopover>
<LegendSettingsPopover
legendOptions={legendOptions}
mode={layer.legendDisplay}
onDisplayChange={(optionId) => {
setState({
...state,
layers: [
{
...layer,
legendDisplay: legendOptions.find(({ id }) => id === optionId)!.value,
},
],
});
}}
position={layer.legendPosition}
onPositionChange={(id) => {
setState({
...state,
layers: [{ ...layer, legendPosition: id as Position }],
});
}}
renderNestedLegendSwitch
nestedLegend={!!layer.nestedLegend}
onNestedLegendChange={() => {
setState({
...state,
layers: [{ ...layer, nestedLegend: !layer.nestedLegend }],
});
}}
/>
</EuiFlexGroup>
);
}
const DecimalPlaceSlider = ({
value,
setValue,
}: {
value: number;
setValue: (value: number) => void;
}) => {
const [localValue, setLocalValue] = useState(value);
useDebounce(() => setValue(localValue), 256, [localValue]);
return (
<EuiRange
data-test-subj="indexPattern-dimension-formatDecimals"
value={localValue}
min={0}
max={10}
showInput
compressed
onChange={(e) => {
setLocalValue(Number(e.currentTarget.value));
}}
/>
);
};
export function DimensionEditor(
props: VisualizationDimensionEditorProps<PieVisualizationState> & {
paletteService: PaletteRegistry;
}
) {
return (
<>
<PalettePicker
palettes={props.paletteService}
activePalette={props.state.palette}
setPalette={(newPalette) => {
props.setState({ ...props.state, palette: newPalette });
}}
/>
</>
);
}