mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* first steps towards threshold line (histogram) * threshold line added for all point_series charts * added settings for threshold line * last fixes * fixed typo * default values for thresholdLineOptions * resolving conflicts * threshold line not displayed when out of the canvas * linting * added color picker for threshold line * fixed assigning of a static color and i18 select options * changing default color and lintings * Fix remaining TS issues
This commit is contained in:
parent
c597b6cf8d
commit
76ed46a4f0
11 changed files with 203 additions and 3 deletions
|
@ -22,6 +22,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { Schemas } from 'ui/vis/editors/default/schemas';
|
||||
import { PointSeriesOptions } from './editors/point_series';
|
||||
import { getLegendPositions, LegendPositions } from './utils/legend_positions';
|
||||
import { palettes } from '@elastic/eui/lib/services';
|
||||
|
||||
export default function PointSeriesVisType(Private) {
|
||||
const VisFactory = Private(VisFactoryProvider);
|
||||
|
@ -97,7 +98,14 @@ export default function PointSeriesVisType(Private) {
|
|||
legendPosition: LegendPositions.RIGHT,
|
||||
times: [],
|
||||
addTimeMarker: false,
|
||||
labels: {},
|
||||
thresholdLine: {
|
||||
show: false,
|
||||
value: 10,
|
||||
width: 1,
|
||||
style: 'full',
|
||||
color: palettes.euiPaletteColorBlind.colors[9]
|
||||
},
|
||||
labels: {}
|
||||
},
|
||||
},
|
||||
editorConfig: {
|
||||
|
|
|
@ -24,6 +24,7 @@ interface NumberInputOptionProps<ParamName extends string> {
|
|||
label?: React.ReactNode;
|
||||
max?: number;
|
||||
min?: number;
|
||||
step?: string | number;
|
||||
paramName: ParamName;
|
||||
value?: number | '';
|
||||
setValue: (paramName: ParamName, value: number | '') => void;
|
||||
|
@ -34,6 +35,7 @@ function NumberInputOption<ParamName extends string>({
|
|||
max,
|
||||
min,
|
||||
paramName,
|
||||
step,
|
||||
value = '',
|
||||
setValue,
|
||||
}: NumberInputOptionProps<ParamName>) {
|
||||
|
@ -41,6 +43,7 @@ function NumberInputOption<ParamName extends string>({
|
|||
<EuiFormRow label={label} fullWidth compressed>
|
||||
<EuiFieldNumber
|
||||
fullWidth
|
||||
step={step}
|
||||
max={max}
|
||||
min={min}
|
||||
value={value}
|
||||
|
|
|
@ -24,7 +24,7 @@ interface SelectOptionProps<ParamName extends string, ValidParamValues extends s
|
|||
id?: string;
|
||||
label: string;
|
||||
labelAppend?: React.ReactNode;
|
||||
options: Array<{ value: ValidParamValues; text: string }>;
|
||||
options: ReadonlyArray<{ readonly value: ValidParamValues; readonly text: string }>;
|
||||
paramName: ParamName;
|
||||
value?: ValidParamValues;
|
||||
setValue: (paramName: ParamName, value: ValidParamValues) => void;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui';
|
||||
import { EuiPanel, EuiTitle, EuiSpacer, EuiColorPicker, EuiFormRow } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
|
@ -26,9 +26,31 @@ import { SwitchOption } from '../controls/switch';
|
|||
import { GridOptions } from '../controls/point_series/grid_options';
|
||||
import { BasicOptions } from '../controls/basic_options';
|
||||
import { BasicVislibParams } from '../types';
|
||||
import { NumberInputOption } from '../controls/number_input';
|
||||
import { SelectOption } from '../controls/select';
|
||||
|
||||
function PointSeriesOptions(props: VisOptionsProps<BasicVislibParams>) {
|
||||
const { stateParams, setValue, vis } = props;
|
||||
const options = [
|
||||
{
|
||||
value: 'full',
|
||||
text: i18n.translate('kbnVislibVisTypes.editors.pointSeries.thresholdLine.style.full', {
|
||||
defaultMessage: 'Full',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'dashed',
|
||||
text: i18n.translate('kbnVislibVisTypes.editors.pointSeries.thresholdLine.style.dashed', {
|
||||
defaultMessage: 'Dashed',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'dot-dashed',
|
||||
text: i18n.translate('kbnVislibVisTypes.editors.pointSeries.thresholdLine.style.dotdashed', {
|
||||
defaultMessage: 'Dot-dashed',
|
||||
}),
|
||||
},
|
||||
] as const;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -82,6 +104,90 @@ function PointSeriesOptions(props: VisOptionsProps<BasicVislibParams>) {
|
|||
<EuiSpacer size="s" />
|
||||
|
||||
<GridOptions {...props} />
|
||||
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<EuiPanel paddingSize="s">
|
||||
<EuiTitle size="xs">
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="kbnVislibVisTypes.editors.pointSeries.thresholdLineSettings"
|
||||
defaultMessage="Threshold Line"
|
||||
/>
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<SwitchOption
|
||||
label={i18n.translate('kbnVislibVisTypes.editors.pointSeries.thresholdLine.show', {
|
||||
defaultMessage: 'Show threshold line',
|
||||
})}
|
||||
paramName="show"
|
||||
value={stateParams.thresholdLine.show}
|
||||
setValue={(paramName, value) =>
|
||||
setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value })
|
||||
}
|
||||
/>
|
||||
|
||||
{stateParams.thresholdLine.show && (
|
||||
<>
|
||||
<NumberInputOption
|
||||
label={i18n.translate(
|
||||
'kbnVislibVisTypes.editors.pointSeries.thresholdLine.valueLabel',
|
||||
{
|
||||
defaultMessage: 'Threshold value',
|
||||
}
|
||||
)}
|
||||
paramName="value"
|
||||
value={stateParams.thresholdLine.value}
|
||||
setValue={(paramName, value) =>
|
||||
setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value || 0 })
|
||||
}
|
||||
/>
|
||||
|
||||
<NumberInputOption
|
||||
label={i18n.translate(
|
||||
'kbnVislibVisTypes.editors.pointSeries.thresholdLine.widthLabel',
|
||||
{
|
||||
defaultMessage: 'Line width',
|
||||
}
|
||||
)}
|
||||
paramName="width"
|
||||
min={1}
|
||||
step={1}
|
||||
value={stateParams.thresholdLine.width}
|
||||
setValue={(paramName, value) =>
|
||||
setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value || 1 })
|
||||
}
|
||||
/>
|
||||
|
||||
<SelectOption
|
||||
label={i18n.translate('kbnVislibVisTypes.editors.pointSeries.thresholdLine.style', {
|
||||
defaultMessage: 'Line style',
|
||||
})}
|
||||
options={options}
|
||||
paramName="style"
|
||||
value={stateParams.thresholdLine.style}
|
||||
setValue={(paramName, value) =>
|
||||
setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value })
|
||||
}
|
||||
/>
|
||||
|
||||
<EuiFormRow
|
||||
label={i18n.translate('kbnVislibVisTypes.editors.pointSeries.thresholdLine.color', {
|
||||
defaultMessage: 'Line color',
|
||||
})}
|
||||
>
|
||||
<EuiColorPicker
|
||||
color={stateParams.thresholdLine.color}
|
||||
onChange={value => {
|
||||
setValue('thresholdLine', { ...stateParams.thresholdLine, color: value });
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</>
|
||||
)}
|
||||
</EuiPanel>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { Schemas } from 'ui/vis/editors/default/schemas';
|
||||
import { PointSeriesOptions } from './editors/point_series';
|
||||
import { getLegendPositions, LegendPositions } from './utils/legend_positions';
|
||||
import { palettes } from '@elastic/eui/lib/services';
|
||||
|
||||
export default function PointSeriesVisType(Private) {
|
||||
const VisFactory = Private(VisFactoryProvider);
|
||||
|
@ -101,6 +102,13 @@ export default function PointSeriesVisType(Private) {
|
|||
addTimeMarker: false,
|
||||
labels: {
|
||||
show: false,
|
||||
},
|
||||
thresholdLine: {
|
||||
show: false,
|
||||
value: 10,
|
||||
width: 1,
|
||||
style: 'full',
|
||||
color: palettes.euiPaletteColorBlind.colors[9]
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -22,6 +22,8 @@ import { i18n } from '@kbn/i18n';
|
|||
import { Schemas } from 'ui/vis/editors/default/schemas';
|
||||
import { PointSeriesOptions } from './editors/point_series';
|
||||
import { getLegendPositions, LegendPositions } from './utils/legend_positions';
|
||||
import { palettes } from '@elastic/eui/lib/services';
|
||||
|
||||
|
||||
export default function PointSeriesVisType(Private) {
|
||||
const VisFactory = Private(VisFactoryProvider);
|
||||
|
@ -98,6 +100,13 @@ export default function PointSeriesVisType(Private) {
|
|||
times: [],
|
||||
addTimeMarker: false,
|
||||
labels: {},
|
||||
thresholdLine: {
|
||||
show: false,
|
||||
value: 10,
|
||||
width: 1,
|
||||
style: 'full',
|
||||
color: palettes.euiPaletteColorBlind.colors[9]
|
||||
}
|
||||
},
|
||||
},
|
||||
editorConfig: {
|
||||
|
|
|
@ -30,6 +30,13 @@ interface Labels {
|
|||
show: boolean;
|
||||
truncate: number;
|
||||
}
|
||||
interface ThresholdLine {
|
||||
show: boolean;
|
||||
value: number;
|
||||
width: number;
|
||||
style: 'full' | 'dashed' | 'dot-dashed';
|
||||
color: string;
|
||||
}
|
||||
export interface ValueAxis {
|
||||
id: string;
|
||||
labels: Labels;
|
||||
|
@ -46,6 +53,7 @@ export interface BasicVislibParams extends CommonVislibParams {
|
|||
addTimeMarker: boolean;
|
||||
orderBucketsBySum?: boolean;
|
||||
labels: Labels;
|
||||
thresholdLine: ThresholdLine;
|
||||
valueAxes: ValueAxis[];
|
||||
grid: {
|
||||
categoryLines: boolean;
|
||||
|
|
|
@ -18,6 +18,15 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { palettes } from '@elastic/eui/lib/services';
|
||||
|
||||
const thresholdLineDefaults = {
|
||||
show: false,
|
||||
value: 10,
|
||||
width: 1,
|
||||
style: 'full',
|
||||
color: palettes.euiPaletteColorBlind.colors[9],
|
||||
};
|
||||
|
||||
export class PointSeries {
|
||||
constructor(handler, seriesEl, seriesData, seriesConfig) {
|
||||
|
@ -26,6 +35,7 @@ export class PointSeries {
|
|||
this.chartEl = seriesEl;
|
||||
this.chartData = seriesData;
|
||||
this.seriesConfig = seriesConfig;
|
||||
this.thresholdLineOptions = _.defaults(handler.visConfig.get('thresholdLine', {}), thresholdLineDefaults);
|
||||
}
|
||||
|
||||
getGroupedCount() {
|
||||
|
@ -80,4 +90,41 @@ export class PointSeries {
|
|||
const click = events.addClickEvent();
|
||||
return element.call(click);
|
||||
}
|
||||
|
||||
addThresholdLine(svgElem) {
|
||||
const chartData = this.chartData;
|
||||
const isHorizontal = this.getCategoryAxis().axisConfig.isHorizontal();
|
||||
const valueAxisDomain = this.getValueAxis().axisScale.getDomain(chartData.values.length);
|
||||
const yScale = this.getValueAxis().getScale();
|
||||
const svgParentWidth = svgElem[0][0].attributes.width.value;
|
||||
const svgParentHeight = svgElem[0][0].attributes.height.value;
|
||||
|
||||
const thresholdLineWidth = this.thresholdLineOptions.width;
|
||||
let thresholdLineStyle = '0';
|
||||
if (this.thresholdLineOptions.style === 'dashed') {
|
||||
thresholdLineStyle = '10,5';
|
||||
} else if (this.thresholdLineOptions.style === 'dot-dashed') {
|
||||
thresholdLineStyle = '20,5,5,5';
|
||||
}
|
||||
const thresholdValue = this.thresholdLineOptions.value;
|
||||
|
||||
const lineColor = this.thresholdLineOptions.color;
|
||||
|
||||
function y(y) {
|
||||
return yScale(y);
|
||||
}
|
||||
|
||||
if (valueAxisDomain && valueAxisDomain[0] <= thresholdValue && valueAxisDomain[1] >= thresholdValue) {
|
||||
svgElem
|
||||
.append('line')
|
||||
.attr('x1', isHorizontal ? 0 : y(thresholdValue))
|
||||
.attr('y1', isHorizontal ? y(thresholdValue) : 0)
|
||||
.attr('x2', isHorizontal ? svgParentWidth : y(thresholdValue))
|
||||
.attr('y2', isHorizontal ? y(thresholdValue) : svgParentHeight)
|
||||
.attr('stroke-width', thresholdLineWidth)
|
||||
.attr('stroke-dasharray', thresholdLineStyle)
|
||||
.attr('stroke', lineColor);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -252,6 +252,9 @@ export class AreaChart extends PointSeries {
|
|||
const circles = self.addCircles(svg, self.chartData);
|
||||
self.addCircleEvents(circles);
|
||||
|
||||
if (self.thresholdLineOptions.show) {
|
||||
self.addThresholdLine(self.chartEl);
|
||||
}
|
||||
self.events.emit('rendered', {
|
||||
chart: self.chartData
|
||||
});
|
||||
|
|
|
@ -367,6 +367,10 @@ export class ColumnChart extends PointSeries {
|
|||
const bars = self.addBars(svg, self.chartData);
|
||||
self.addCircleEvents(bars);
|
||||
|
||||
if (self.thresholdLineOptions.show) {
|
||||
self.addThresholdLine(self.chartEl);
|
||||
}
|
||||
|
||||
self.events.emit('rendered', {
|
||||
chart: self.chartData
|
||||
});
|
||||
|
|
|
@ -224,6 +224,10 @@ export class LineChart extends PointSeries {
|
|||
const circles = self.addCircles(svg, self.chartData);
|
||||
self.addCircleEvents(circles);
|
||||
|
||||
if (self.thresholdLineOptions.show) {
|
||||
self.addThresholdLine(self.chartEl);
|
||||
}
|
||||
|
||||
self.events.emit('rendered', {
|
||||
chart: self.chartData
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue