(paramName: T, value: ValueAxis[T]): void;
+ setValueAxisScale: SetScale;
+}
+
+function CustomExtentsOptions({
+ axis,
+ setMultipleValidity,
+ setValueAxis,
+ setValueAxisScale,
+}: CustomExtentsOptionsProps) {
+ const [isBoundsMarginValid, setIsBoundsMarginValid] = useState(true);
+ const invalidBoundsMarginMessage = i18n.translate(
+ 'kbnVislibVisTypes.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin',
+ { defaultMessage: 'Bounds margin must be greater than or equal to 0.' }
+ );
+
+ const setBoundsMargin = useCallback(
+ (paramName: 'boundsMargin', value: number | '') => {
+ const isValid = value === '' ? true : value >= 0;
+ setIsBoundsMarginValid(isValid);
+ setMultipleValidity('boundsMargin', isValid);
+
+ setValueAxisScale(paramName, value);
+ },
+ [setMultipleValidity, setValueAxisScale]
+ );
+
+ const onDefaultYExtentsChange = useCallback(
+ (paramName: 'defaultYExtents', value: boolean) => {
+ const scale = { ...axis.scale, [paramName]: value };
+ if (!scale.defaultYExtents) {
+ delete scale.boundsMargin;
+ setMultipleValidity('boundsMargin', true);
+ }
+ setValueAxis('scale', scale);
+ },
+ [setValueAxis, axis.scale]
+ );
+
+ const onSetYExtentsChange = useCallback(
+ (paramName: 'setYExtents', value: boolean) => {
+ const scale = { ...axis.scale, [paramName]: value };
+ if (!scale.setYExtents) {
+ delete scale.min;
+ delete scale.max;
+ }
+ setValueAxis('scale', scale);
+ },
+ [setValueAxis, axis.scale]
+ );
+
+ return (
+ <>
+
+
+ {axis.scale.defaultYExtents && (
+ <>
+
+ >
+ )}
+
+
+
+ {axis.scale.setYExtents && (
+
+ )}
+ >
+ );
+}
+
+export { CustomExtentsOptions };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx
new file mode 100644
index 0000000000000..05797b8dde5b2
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx
@@ -0,0 +1,307 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useState, useEffect, useCallback, useMemo } from 'react';
+import { cloneDeep, uniq, get } from 'lodash';
+import { EuiSpacer } from '@elastic/eui';
+
+import { AggConfig } from 'ui/vis';
+import { BasicVislibParams, ValueAxis, SeriesParam, Axis } from '../../../types';
+import { ValidationVisOptionsProps } from '../../common';
+import { SeriesPanel } from './series_panel';
+import { CategoryAxisPanel } from './category_axis_panel';
+import { ValueAxesPanel } from './value_axes_panel';
+import {
+ makeSerie,
+ isAxisHorizontal,
+ countNextAxisNumber,
+ getUpdatedAxisName,
+ mapPositionOpposite,
+ mapPosition,
+} from './utils';
+
+export type SetParamByIndex = (
+ axesName: 'valueAxes' | 'seriesParams',
+ index: number,
+ paramName: P | O,
+ value: ValueAxis[P] | SeriesParam[O]
+) => void;
+
+export type ChangeValueAxis = (
+ index: number,
+ paramName: 'valueAxis',
+ selectedValueAxis: string
+) => void;
+
+const VALUE_AXIS_PREFIX = 'ValueAxis-';
+
+function MetricsAxisOptions(props: ValidationVisOptionsProps) {
+ const { stateParams, setValue, aggs, aggsLabels, setVisType, vis } = props;
+
+ const [isCategoryAxisHorizontal, setIsCategoryAxisHorizontal] = useState(true);
+
+ const setParamByIndex: SetParamByIndex = useCallback(
+ (axesName, index, paramName, value) => {
+ const items = stateParams[axesName];
+ const array = [...items] as typeof items;
+
+ array[index] = {
+ ...array[index],
+ [paramName]: value,
+ };
+
+ setValue(axesName, array);
+ },
+ [stateParams, setValue]
+ );
+
+ const setCategoryAxis = useCallback(
+ (value: Axis) => {
+ const categoryAxes = [...stateParams.categoryAxes];
+ categoryAxes[0] = value;
+ setValue('categoryAxes', categoryAxes);
+ },
+ [setValue, stateParams.categoryAxes]
+ );
+
+ // stores previous aggs' custom labels
+ const [lastCustomLabels, setLastCustomLabels] = useState({} as { [key: string]: string });
+ // stores previous aggs' field and type
+ const [lastSeriesAgg, setLastSeriesAgg] = useState({} as {
+ [key: string]: { type: string; field: string };
+ });
+
+ const updateAxisTitle = () => {
+ const axes = cloneDeep(stateParams.valueAxes);
+ let isAxesChanged = false;
+ const lastLabels = { ...lastCustomLabels };
+ const lastMatchingSeriesAgg = { ...lastSeriesAgg };
+
+ stateParams.valueAxes.forEach((axis, axisNumber) => {
+ let newCustomLabel = '';
+ const matchingSeries: AggConfig[] = [];
+
+ stateParams.seriesParams.forEach((series, seriesIndex) => {
+ if ((axisNumber === 0 && !series.valueAxis) || series.valueAxis === axis.id) {
+ const aggByIndex = aggs.bySchemaName('metric')[seriesIndex];
+ matchingSeries.push(aggByIndex);
+ }
+ });
+
+ if (matchingSeries.length === 1) {
+ // if several series matches to the axis, axis title is set according to the first serie.
+ newCustomLabel = matchingSeries[0].makeLabel();
+ }
+
+ if (lastCustomLabels[axis.id] !== newCustomLabel && newCustomLabel !== '') {
+ const lastSeriesAggType = get(lastSeriesAgg, `${matchingSeries[0].id}.type`);
+ const lastSeriesAggField = get(lastSeriesAgg, `${matchingSeries[0].id}.field`);
+ const matchingSeriesAggType = get(matchingSeries, '[0]type.name', '');
+ const matchingSeriesAggField = get(matchingSeries, '[0]params.field.name', '');
+
+ const aggTypeIsChanged = lastSeriesAggType !== matchingSeriesAggType;
+ const aggFieldIsChanged = lastSeriesAggField !== matchingSeriesAggField;
+
+ lastMatchingSeriesAgg[matchingSeries[0].id] = {
+ type: matchingSeriesAggType,
+ field: matchingSeriesAggField,
+ };
+ lastLabels[axis.id] = newCustomLabel;
+
+ if (
+ aggTypeIsChanged ||
+ aggFieldIsChanged ||
+ axis.title.text === '' ||
+ lastCustomLabels[axis.id] === axis.title.text
+ ) {
+ // Override axis title with new custom label
+ axes[axisNumber] = { ...axes[axisNumber], title: { ...axis, text: newCustomLabel } };
+ isAxesChanged = true;
+ }
+ }
+ });
+
+ if (isAxesChanged) {
+ setValue('valueAxes', axes);
+ }
+
+ setLastSeriesAgg(lastMatchingSeriesAgg);
+ setLastCustomLabels(lastLabels);
+ };
+
+ const onValueAxisPositionChanged = useCallback(
+ (index: number, value: ValueAxis['position']) => {
+ const valueAxes = [...stateParams.valueAxes];
+ const name = getUpdatedAxisName(value, valueAxes);
+
+ valueAxes[index] = {
+ ...valueAxes[index],
+ name,
+ position: value,
+ };
+ setValue('valueAxes', valueAxes);
+ },
+ [stateParams.valueAxes, getUpdatedAxisName, setValue]
+ );
+
+ const onCategoryAxisPositionChanged = useCallback(
+ (chartPosition: Axis['position']) => {
+ const isChartHorizontal = isAxisHorizontal(chartPosition);
+ setIsCategoryAxisHorizontal(isAxisHorizontal(chartPosition));
+
+ stateParams.valueAxes.forEach((axis, index) => {
+ if (isAxisHorizontal(axis.position) === isChartHorizontal) {
+ const position = mapPosition(axis.position);
+ onValueAxisPositionChanged(index, position);
+ }
+ });
+ },
+ [stateParams.valueAxes, onValueAxisPositionChanged]
+ );
+
+ const addValueAxis = useCallback(() => {
+ const nextAxisIdNumber = stateParams.valueAxes.reduce(
+ countNextAxisNumber(VALUE_AXIS_PREFIX),
+ 1
+ );
+
+ const newAxis = cloneDeep(stateParams.valueAxes[0]);
+ newAxis.id = VALUE_AXIS_PREFIX + nextAxisIdNumber;
+ newAxis.position = mapPositionOpposite(newAxis.position);
+ newAxis.name = getUpdatedAxisName(newAxis.position, stateParams.valueAxes);
+
+ setValue('valueAxes', [...stateParams.valueAxes, newAxis]);
+ return newAxis;
+ }, [stateParams.valueAxes, setValue]);
+
+ const removeValueAxis = useCallback(
+ (axis: ValueAxis) => {
+ const newValueAxes = stateParams.valueAxes.filter(valAxis => valAxis.id !== axis.id);
+
+ setValue('valueAxes', newValueAxes);
+
+ let isSeriesUpdated = false;
+ const series = stateParams.seriesParams.map(ser => {
+ if (axis.id === ser.valueAxis) {
+ isSeriesUpdated = true;
+ return { ...ser, valueAxis: newValueAxes[0].id };
+ }
+ return ser;
+ });
+
+ if (isSeriesUpdated) {
+ // if seriesParams have valueAxis equals to removed one, then we reset it to the first valueAxis
+ setValue('seriesParams', series);
+ }
+
+ if (stateParams.grid.valueAxis === axis.id) {
+ // reset Y-axis grid lines setting
+ setValue('grid', { ...stateParams.grid, valueAxis: undefined });
+ }
+ },
+ [stateParams.seriesParams, stateParams.valueAxes, setValue]
+ );
+
+ const changeValueAxis: ChangeValueAxis = useCallback(
+ (index, paramName, selectedValueAxis) => {
+ let newValueAxis = selectedValueAxis;
+ if (selectedValueAxis === 'new') {
+ const axis = addValueAxis();
+ newValueAxis = axis.id;
+ }
+
+ setParamByIndex('seriesParams', index, paramName, newValueAxis);
+
+ updateAxisTitle();
+ },
+ [addValueAxis, setParamByIndex]
+ );
+
+ const metrics = useMemo(() => {
+ const schemaName = vis.type.schemas.metrics[0].name;
+ return aggs.bySchemaName(schemaName);
+ }, [vis.type.schemas.metrics[0].name, aggs, aggsLabels]);
+
+ const firstValueAxesId = stateParams.valueAxes[0].id;
+
+ useEffect(() => {
+ const updatedSeries = metrics.map(agg => {
+ const params = stateParams.seriesParams.find(param => param.data.id === agg.id);
+ const label = agg.makeLabel();
+
+ // update labels for existing params or create new one
+ if (params) {
+ return {
+ ...params,
+ data: {
+ ...params.data,
+ label,
+ },
+ };
+ } else {
+ const series = makeSerie(
+ agg.id,
+ label,
+ firstValueAxesId,
+ stateParams.seriesParams[stateParams.seriesParams.length - 1]
+ );
+ return series;
+ }
+ });
+
+ setValue('seriesParams', updatedSeries);
+ }, [aggsLabels, metrics, firstValueAxesId]);
+
+ const visType = useMemo(() => {
+ const types = uniq(stateParams.seriesParams.map(({ type }) => type));
+ return types.length === 1 ? types[0] : 'histogram';
+ }, [stateParams.seriesParams]);
+
+ useEffect(() => {
+ setVisType(visType);
+ }, [visType]);
+
+ useEffect(() => {
+ updateAxisTitle();
+ }, [aggsLabels]);
+
+ return (
+ <>
+
+
+
+
+
+ >
+ );
+}
+
+export { MetricsAxisOptions };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/label_options.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/label_options.tsx
new file mode 100644
index 0000000000000..62ad2601f0e33
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/label_options.tsx
@@ -0,0 +1,124 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useCallback } from 'react';
+import { EuiTitle, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import { VisOptionsProps } from 'ui/vis/editors/default';
+import { BasicVislibParams, Axis } from '../../../types';
+import { SelectOption, SwitchOption, TruncateLabelsOption } from '../../common';
+import { rotateOptions } from '../../../utils/collections';
+
+interface LabelOptionsProps extends VisOptionsProps {
+ axis: Axis;
+ axesName: 'categoryAxes' | 'valueAxes';
+ index: number;
+}
+
+function LabelOptions({ stateParams, setValue, axis, axesName, index }: LabelOptionsProps) {
+ const setAxisLabel = useCallback(
+ (paramName: T, value: Axis['labels'][T]) => {
+ const axes = [...stateParams[axesName]];
+ axes[index] = {
+ ...axes[index],
+ labels: {
+ ...axes[index].labels,
+ [paramName]: value,
+ },
+ };
+ setValue(axesName, axes);
+ },
+ [axesName, index, setValue, stateParams]
+ );
+
+ const setAxisLabelRotate = useCallback(
+ (paramName: 'rotate', value: Axis['labels']['rotate']) => {
+ setAxisLabel(paramName, Number(value));
+ },
+ [setAxisLabel]
+ );
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
+
+export { LabelOptions };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/line_options.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/line_options.tsx
new file mode 100644
index 0000000000000..eb1ed014e7e96
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/line_options.tsx
@@ -0,0 +1,94 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useCallback } from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+
+import { Vis } from 'ui/vis';
+import { SeriesParam } from '../../../types';
+import { NumberInputOption, SelectOption, SwitchOption } from '../../common';
+import { SetChart } from './chart_options';
+
+interface LineOptionsParams {
+ chart: SeriesParam;
+ vis: Vis;
+ setChart: SetChart;
+}
+
+function LineOptions({ chart, vis, setChart }: LineOptionsParams) {
+ const setLineWidth = useCallback(
+ (paramName: 'lineWidth', value: number | '') => {
+ setChart(paramName, value === '' ? undefined : value);
+ },
+ [setChart]
+ );
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
+
+export { LineOptions };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/series_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/series_panel.tsx
new file mode 100644
index 0000000000000..816b0bfeda598
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/series_panel.tsx
@@ -0,0 +1,77 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { EuiPanel, EuiTitle, EuiSpacer, EuiAccordion } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import { VisOptionsProps } from 'ui/vis/editors/default';
+import { BasicVislibParams } from '../../../types';
+import { ChartOptions } from './chart_options';
+import { SetParamByIndex, ChangeValueAxis } from './';
+
+interface SeriesPanelProps extends VisOptionsProps {
+ changeValueAxis: ChangeValueAxis;
+ setParamByIndex: SetParamByIndex;
+}
+
+function SeriesPanel(props: SeriesPanelProps) {
+ const { stateParams } = props;
+
+ return (
+
+
+
+
+
+
+
+
+ {stateParams.seriesParams.map((chart, index) => (
+
+ <>
+
+
+
+ >
+
+ ))}
+
+ );
+}
+
+export { SeriesPanel };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/utils.ts b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/utils.ts
new file mode 100644
index 0000000000000..7144b0ad4902e
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/utils.ts
@@ -0,0 +1,111 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { capitalize } from 'lodash';
+
+import { BasicVislibParams, ValueAxis, SeriesParam } from '../../../types';
+import { ChartModes, ChartTypes, InterpolationModes, Positions } from '../../../utils/collections';
+
+const makeSerie = (
+ id: string,
+ label: string,
+ defaultValueAxis: ValueAxis['id'],
+ lastSerie?: SeriesParam
+): SeriesParam => {
+ const data = { id, label };
+ const defaultSerie = {
+ show: true,
+ mode: ChartModes.NORMAL,
+ type: ChartTypes.LINE,
+ drawLinesBetweenPoints: true,
+ showCircles: true,
+ interpolate: InterpolationModes.LINEAR,
+ lineWidth: 2,
+ valueAxis: defaultValueAxis,
+ data,
+ };
+ return lastSerie ? { ...lastSerie, data } : defaultSerie;
+};
+
+const isAxisHorizontal = (position: Positions) =>
+ [Positions.TOP, Positions.BOTTOM].includes(position);
+
+const RADIX = 10;
+
+function countNextAxisNumber(axisName: string, axisProp: 'id' | 'name' = 'id') {
+ return (value: number, axis: ValueAxis) => {
+ const nameLength = axisName.length;
+ if (axis[axisProp].substr(0, nameLength) === axisName) {
+ const num = parseInt(axis[axisProp].substr(nameLength), RADIX);
+ if (num >= value) {
+ value = num + 1;
+ }
+ }
+ return value;
+ };
+}
+
+const AXIS_PREFIX = 'Axis-';
+
+const getUpdatedAxisName = (
+ axisPosition: ValueAxis['position'],
+ valueAxes: BasicVislibParams['valueAxes']
+) => {
+ const axisName = capitalize(axisPosition) + AXIS_PREFIX;
+ const nextAxisNameNumber = valueAxes.reduce(countNextAxisNumber(axisName, 'name'), 1);
+
+ return `${axisName}${nextAxisNameNumber}`;
+};
+
+function mapPositionOpposite(position: Positions) {
+ switch (position) {
+ case Positions.BOTTOM:
+ return Positions.TOP;
+ case Positions.TOP:
+ return Positions.BOTTOM;
+ case Positions.LEFT:
+ return Positions.RIGHT;
+ case Positions.RIGHT:
+ return Positions.LEFT;
+ default:
+ throw new Error('Invalid legend position.');
+ }
+}
+
+function mapPosition(position: Positions) {
+ switch (position) {
+ case Positions.BOTTOM:
+ return Positions.LEFT;
+ case Positions.TOP:
+ return Positions.RIGHT;
+ case Positions.LEFT:
+ return Positions.BOTTOM;
+ case Positions.RIGHT:
+ return Positions.TOP;
+ }
+}
+
+export {
+ makeSerie,
+ isAxisHorizontal,
+ countNextAxisNumber,
+ getUpdatedAxisName,
+ mapPositionOpposite,
+ mapPosition,
+};
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.tsx
new file mode 100644
index 0000000000000..2ae54f9e09337
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.tsx
@@ -0,0 +1,162 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useCallback, useMemo } from 'react';
+import {
+ EuiPanel,
+ EuiTitle,
+ EuiSpacer,
+ EuiAccordion,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiButtonIcon,
+ EuiToolTip,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import { BasicVislibParams, ValueAxis } from '../../../types';
+import { ValueAxisOptions } from './value_axis_options';
+import { SetParamByIndex } from './';
+import { ValidationVisOptionsProps } from '../../common';
+
+interface ValueAxesPanelProps extends ValidationVisOptionsProps {
+ isCategoryAxisHorizontal: boolean;
+ addValueAxis: () => ValueAxis;
+ removeValueAxis: (axis: ValueAxis) => void;
+ onValueAxisPositionChanged: (index: number, value: ValueAxis['position']) => void;
+ setParamByIndex: SetParamByIndex;
+}
+
+function ValueAxesPanel(props: ValueAxesPanelProps) {
+ const { stateParams, addValueAxis, removeValueAxis } = props;
+
+ const getSeries = useCallback(
+ (axis: ValueAxis) => {
+ const isFirst = stateParams.valueAxes[0].id === axis.id;
+ const series = stateParams.seriesParams.filter(
+ serie => serie.valueAxis === axis.id || (isFirst && !serie.valueAxis)
+ );
+ return series.map(serie => serie.data.label).join(', ');
+ },
+ [stateParams.valueAxes, stateParams.seriesParams]
+ );
+
+ const removeButtonTooltip = useMemo(
+ () =>
+ i18n.translate('kbnVislibVisTypes.controls.pointSeries.valueAxes.removeButtonTooltip', {
+ defaultMessage: 'Remove Y-axis',
+ }),
+ []
+ );
+
+ const renderRemoveButton = useCallback(
+ (axis: ValueAxis) => (
+
+ removeValueAxis(axis)}
+ aria-label={removeButtonTooltip}
+ />
+
+ ),
+ [removeValueAxis]
+ );
+
+ const addButtonTooltip = useMemo(
+ () =>
+ i18n.translate('kbnVislibVisTypes.controls.pointSeries.valueAxes.addButtonTooltip', {
+ defaultMessage: 'Add Y-axis',
+ }),
+ []
+ );
+
+ const getButtonContent = useCallback(
+ (axis: ValueAxis) => {
+ const description = getSeries(axis);
+
+ return (
+ <>
+ {axis.name}{' '}
+
+ <>{description}>
+
+ >
+ );
+ },
+ [getSeries]
+ );
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {stateParams.valueAxes.map((axis, index) => (
+
+ <>
+
+
+ >
+
+ ))}
+
+ );
+}
+
+export { ValueAxesPanel };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axis_options.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axis_options.tsx
new file mode 100644
index 0000000000000..00b3f719a49de
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axis_options.tsx
@@ -0,0 +1,219 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useCallback, useMemo } from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiSpacer, EuiAccordion, EuiHorizontalRule } from '@elastic/eui';
+
+import { BasicVislibParams, ValueAxis } from '../../../types';
+import { Positions } from '../../../utils/collections';
+import {
+ SelectOption,
+ SwitchOption,
+ TextInputOption,
+ ValidationVisOptionsProps,
+} from '../../common';
+import { LabelOptions } from './label_options';
+import { CustomExtentsOptions } from './custom_extents_options';
+import { isAxisHorizontal } from './utils';
+import { SetParamByIndex } from './';
+
+export type SetScale = (
+ paramName: T,
+ value: ValueAxis['scale'][T]
+) => void;
+
+export interface ValueAxisOptionsParams extends ValidationVisOptionsProps {
+ axis: ValueAxis;
+ index: number;
+ isCategoryAxisHorizontal: boolean;
+ onValueAxisPositionChanged: (index: number, value: ValueAxis['position']) => void;
+ setParamByIndex: SetParamByIndex;
+}
+
+function ValueAxisOptions(props: ValueAxisOptionsParams) {
+ const {
+ axis,
+ index,
+ isCategoryAxisHorizontal,
+ stateParams,
+ vis,
+ onValueAxisPositionChanged,
+ setParamByIndex,
+ } = props;
+
+ const setValueAxis = useCallback(
+ (paramName: T, value: ValueAxis[T]) =>
+ setParamByIndex('valueAxes', index, paramName, value),
+ [setParamByIndex, index]
+ );
+
+ const setValueAxisTitle = useCallback(
+ (paramName: T, value: ValueAxis['title'][T]) => {
+ const title = {
+ ...stateParams.valueAxes[index].title,
+ [paramName]: value,
+ };
+
+ setParamByIndex('valueAxes', index, 'title', title);
+ },
+ [setParamByIndex, index, stateParams.valueAxes]
+ );
+
+ const setValueAxisScale: SetScale = useCallback(
+ (paramName, value) => {
+ const scale = {
+ ...stateParams.valueAxes[index].scale,
+ [paramName]: value,
+ };
+
+ setParamByIndex('valueAxes', index, 'scale', scale);
+ },
+ [setParamByIndex, index, stateParams.valueAxes]
+ );
+
+ const onPositionChanged = useCallback(
+ (paramName: 'position', value: ValueAxis['position']) => {
+ onValueAxisPositionChanged(index, value);
+ },
+ [index, onValueAxisPositionChanged]
+ );
+
+ const isPositionDisabled = useCallback(
+ (position: Positions) => {
+ if (isCategoryAxisHorizontal) {
+ return isAxisHorizontal(position);
+ }
+ return [Positions.LEFT, Positions.RIGHT].includes(position);
+ },
+ [isCategoryAxisHorizontal]
+ );
+
+ const positions = useMemo(
+ () =>
+ vis.type.editorConfig.collections.positions.map(
+ (position: { text: string; value: Positions }) => ({
+ ...position,
+ disabled: isPositionDisabled(position.value),
+ })
+ ),
+ [vis.type.editorConfig.collections.positions, isPositionDisabled]
+ );
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ {axis.show ? (
+ <>
+
+
+
+
+ >
+ ) : (
+
+ )}
+
+
+
+
+ <>
+
+
+ >
+
+ >
+ );
+}
+
+export { ValueAxisOptions };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/y_extents.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/y_extents.tsx
new file mode 100644
index 0000000000000..29b986367d72a
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/y_extents.tsx
@@ -0,0 +1,120 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useEffect, useCallback } from 'react';
+import { EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { Scale } from '../../../types';
+import { ScaleTypes } from '../../../utils/collections';
+import { NumberInputOption } from '../../common';
+import { SetScale } from './value_axis_options';
+
+const rangeError = i18n.translate(
+ 'kbnVislibVisTypes.controls.pointSeries.valueAxes.minErrorMessage',
+ { defaultMessage: 'Min should be less than Max.' }
+);
+const minError = i18n.translate(
+ 'kbnVislibVisTypes.controls.pointSeries.valueAxes.minNeededScaleText',
+ {
+ defaultMessage: 'Min must exceed 0 when a log scale is selected.',
+ }
+);
+
+function areExtentsValid(min: number | null = null, max: number | null = null): boolean {
+ if (min === null || max === null) {
+ return true;
+ }
+
+ return max > min;
+}
+
+function isNullOrUndefined(value?: number | null): value is null | undefined {
+ return value === null || value === undefined;
+}
+
+interface YExtentsProps {
+ scale: Scale;
+ setScale: SetScale;
+ setMultipleValidity: (paramName: string, isValid: boolean) => void;
+}
+
+function YExtents({ scale, setScale, setMultipleValidity }: YExtentsProps) {
+ const { min, max, type } = scale;
+ const errors = [];
+
+ if (!areExtentsValid(min, max)) {
+ errors.push(rangeError);
+ }
+
+ if (type === ScaleTypes.LOG && (isNullOrUndefined(min) || min <= 0)) {
+ errors.push(minError);
+ }
+
+ const isValid = !errors.length;
+
+ const setExtents = useCallback(
+ (paramName, value) => {
+ setScale(paramName, value === '' ? null : value);
+ },
+ [setScale]
+ );
+
+ useEffect(() => {
+ setMultipleValidity('yExtents', isValid);
+
+ return () => setMultipleValidity('yExtents', true);
+ }, [isValid]);
+
+ return (
+
+ <>
+
+
+
+
+
+
+
+
+ >
+
+ );
+}
+
+export { YExtents };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/grid_options.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/grid_panel.tsx
similarity index 84%
rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/grid_options.tsx
rename to src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/grid_panel.tsx
index d155ad938bf48..6493fdd59868f 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/grid_options.tsx
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/grid_panel.tsx
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import React, { useMemo, useEffect } from 'react';
+import React, { useMemo, useEffect, useCallback } from 'react';
import { EuiPanel, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -25,15 +25,14 @@ import { VisOptionsProps } from 'ui/vis/editors/default';
import { SelectOption, SwitchOption } from '../../common';
import { BasicVislibParams, ValueAxis } from '../../../types';
-function GridOptions({
- stateParams,
- setValue,
- hasHistogramAgg,
-}: VisOptionsProps) {
- const setGrid = (
- paramName: T,
- value: BasicVislibParams['grid'][T]
- ) => setValue('grid', { ...stateParams.grid, [paramName]: value });
+function GridPanel({ stateParams, setValue, hasHistogramAgg }: VisOptionsProps) {
+ const setGrid = useCallback(
+ (
+ paramName: T,
+ value: BasicVislibParams['grid'][T]
+ ) => setValue('grid', { ...stateParams.grid, [paramName]: value }),
+ [stateParams.grid, setValue]
+ );
const options = useMemo(
() => [
@@ -48,7 +47,7 @@ function GridOptions({
value: '',
},
],
- [stateParams.valueAxes.map(({ id }: ValueAxis) => id)]
+ [stateParams.valueAxes]
);
useEffect(() => {
@@ -71,7 +70,7 @@ function GridOptions({
) {
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 (
<>
@@ -100,91 +81,11 @@ function PointSeriesOptions(props: VisOptionsProps) {
-
+
-
-
-
-
-
-
-
-
-
- setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value })
- }
- />
-
- {stateParams.thresholdLine.show && (
- <>
-
- setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value || 0 })
- }
- />
-
-
- setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value || 1 })
- }
- />
-
-
- setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value })
- }
- />
-
-
- {
- setValue('thresholdLine', { ...stateParams.thresholdLine, color: value });
- }}
- />
-
- >
- )}
-
+ {stateParams.thresholdLine && }
>
);
}
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx
new file mode 100644
index 0000000000000..331b81dc65321
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx
@@ -0,0 +1,126 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import React, { useCallback } from 'react';
+import { EuiPanel, EuiTitle, EuiColorPicker, EuiFormRow, EuiSpacer } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import { VisOptionsProps } from 'ui/vis/editors/default';
+import { NumberInputOption, SelectOption, SwitchOption } from '../../common';
+import { BasicVislibParams } from '../../../types';
+
+function ThresholdPanel({ stateParams, setValue, vis }: VisOptionsProps) {
+ const setThresholdLine = useCallback(
+ (
+ paramName: T,
+ value: BasicVislibParams['thresholdLine'][T]
+ ) => setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value }),
+ [stateParams.thresholdLine, setValue]
+ );
+
+ const setThresholdLineColor = useCallback(
+ (value: BasicVislibParams['thresholdLine']['color']) => setThresholdLine('color', value),
+ [setThresholdLine]
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ {stateParams.thresholdLine.show && (
+ <>
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
+ );
+}
+
+export { ThresholdPanel };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/category_axis.html b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/category_axis.html
deleted file mode 100644
index 0d6f804ef87ae..0000000000000
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/category_axis.html
+++ /dev/null
@@ -1,134 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/category_axis.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/category_axis.js
deleted file mode 100644
index 3b31ad8c1fb78..0000000000000
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/category_axis.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { uiModules } from 'ui/modules';
-import vislibValueAxesTemplate from './category_axis.html';
-const module = uiModules.get('kibana');
-
-module.directive('vislibCategoryAxis', function () {
- return {
- restrict: 'E',
- template: vislibValueAxesTemplate,
- replace: true,
- link: function ($scope) {
- $scope.rotateOptions = [
- { name: 'horizontal', value: 0 },
- { name: 'vertical', value: 90 },
- { name: 'angled', value: 75 },
- ];
- }
- };
-});
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/index.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/index.js
deleted file mode 100644
index 87289e9aa410d..0000000000000
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import './value_axes.js';
-import './category_axis.js';
-import './series.js';
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/series.html b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/series.html
deleted file mode 100644
index d96c1b73e8551..0000000000000
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/series.html
+++ /dev/null
@@ -1,156 +0,0 @@
-
-
-
-
-
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/series.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/series.js
deleted file mode 100644
index 6b0b5511ca47a..0000000000000
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/series.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import _ from 'lodash';
-import { uiModules } from 'ui/modules';
-import vislibSeriesTemplate from './series.html';
-import { safeMakeLabel } from 'ui/agg_types/agg_utils';
-
-const module = uiModules.get('kibana');
-
-module.directive('vislibSeries', function () {
- return {
- restrict: 'E',
- template: vislibSeriesTemplate,
- replace: true,
- link: function ($scope) {
- function makeSerie(id, label) {
- const last = $scope.series[$scope.series.length - 1];
- return {
- show: true,
- mode: last ? last.mode : 'normal',
- type: last ? last.type : 'line',
- drawLinesBetweenPoints: last ? last.drawLinesBetweenPoints : true,
- showCircles: last ? last.showCircles : true,
- interpolate: last ? last.interpolate : 'linear',
- lineWidth: last ? last.lineWidth : 2,
- data: {
- id: id,
- label: label
- },
- valueAxis: last ? last.valueAxis : $scope.editorState.params.valueAxes[0].id
- };
- }
-
- $scope.series = $scope.editorState.params.seriesParams;
- $scope.$watch(() => {
- return $scope.editorState.aggs.aggs.map(agg => {
- return safeMakeLabel(agg);
- }).join();
- }, () => {
- const schemaTitle = $scope.vis.type.schemas.metrics[0].title;
-
- const metrics = $scope.editorState.aggs.aggs.filter(agg => {
- const isMetric = agg.type && agg.type.type === 'metrics';
- return isMetric && agg.schema.title === schemaTitle;
- });
-
- // update labels for existing params or create new one
- $scope.editorState.params.seriesParams = metrics.map(agg => {
- const params = $scope.editorState.params.seriesParams.find(param => param.data.id === agg.id);
- if (params) {
- params.data.label = agg.makeLabel();
- return params;
- } else {
- const series = makeSerie(agg.id, agg.makeLabel());
- return series;
- }
- });
- });
-
- $scope.$watch(() => {
- return $scope.editorState.params.seriesParams.map(series => series.type).join();
- }, () => {
- const types = _.uniq(_.map($scope.editorState.params.seriesParams, 'type'));
- $scope.vis.type.type = types.length === 1 ? types[0] : 'histogram';
- });
-
- $scope.$watch('editorState.params.valueAxes.length', () => {
- $scope.editorState.params.seriesParams.forEach(series => {
- if (!$scope.editorState.params.valueAxes.find(axis => axis.id === series.valueAxis)) {
- series.valueAxis = $scope.editorState.params.valueAxes[0].id;
- }
- });
- });
-
- $scope.changeValueAxis = (index) => {
- const series = $scope.editorState.params.seriesParams[index];
- if (series.valueAxis === 'new') {
- const axis = $scope.addValueAxis();
- series.valueAxis = axis.id;
- }
- $scope.updateAxisTitle();
- };
- }
- };
-});
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/value_axes.html b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/value_axes.html
deleted file mode 100644
index 5b316bd2ef420..0000000000000
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/value_axes.html
+++ /dev/null
@@ -1,350 +0,0 @@
-
-
-
-
-
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/value_axes.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/value_axes.js
deleted file mode 100644
index bc790306dc2d3..0000000000000
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/value_axes.js
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import _ from 'lodash';
-import { uiModules } from 'ui/modules';
-import vislibValueAxesTemplate from './value_axes.html';
-import { safeMakeLabel } from 'ui/agg_types/agg_utils';
-
-const module = uiModules.get('kibana');
-
-module.directive('vislibValueAxes', function () {
- return {
- restrict: 'E',
- template: vislibValueAxesTemplate,
- replace: true,
- link: function ($scope) {
- let isCategoryAxisHorizontal = true;
-
- function mapPosition(position) {
- switch (position) {
- case 'bottom': return 'left';
- case 'top': return 'right';
- case 'left': return 'bottom';
- case 'right': return 'top';
- }
- }
-
- function mapPositionOpposite(position) {
- switch (position) {
- case 'bottom': return 'top';
- case 'top': return 'bottom';
- case 'left': return 'right';
- case 'right': return 'left';
- }
- }
-
- $scope.rotateOptions = [
- { name: 'horizontal', value: 0 },
- { name: 'vertical', value: 90 },
- { name: 'angled', value: 75 },
- ];
-
- $scope.$watch('editorState.params.categoryAxes[0].position', position => {
- isCategoryAxisHorizontal = ['top', 'bottom'].includes(position);
- $scope.editorState.params.valueAxes.forEach(axis => {
- const axisIsHorizontal = ['top', 'bottom'].includes(axis.position);
- if (axisIsHorizontal === isCategoryAxisHorizontal) {
- axis.position = mapPosition(axis.position);
- $scope.updateAxisName(axis);
- }
- });
- });
-
- $scope.getSeries = function (axis) {
- const isFirst = $scope.editorState.params.valueAxes[0] === axis;
- const series = $scope.editorState.params.seriesParams.filter(series =>
- (series.valueAxis === axis.id || (isFirst && !series.valueAxis))
- );
- return series.map(series => series.data.label).join(', ');
- };
-
- $scope.getSeriesShort = function (axis) {
- const maxStringLength = 30;
- return $scope.getSeries(axis).substring(0, maxStringLength);
- };
-
- $scope.isPositionDisabled = function (position) {
- if (isCategoryAxisHorizontal) {
- return ['top', 'bottom'].includes(position);
- }
- return ['left', 'right'].includes(position);
- };
-
- $scope.addValueAxis = function () {
- const firstAxis = $scope.editorState.params.valueAxes[0];
- const newAxis = _.cloneDeep(firstAxis);
- newAxis.id = 'ValueAxis-' + $scope.editorState.params.valueAxes.reduce((value, axis) => {
- if (axis.id.substr(0, 10) === 'ValueAxis-') {
- const num = parseInt(axis.id.substr(10));
- if (num >= value) value = num + 1;
- }
- return value;
- }, 1);
-
- newAxis.position = mapPositionOpposite(firstAxis.position);
- const axisName = _.capitalize(newAxis.position) + 'Axis-';
- newAxis.name = axisName + $scope.editorState.params.valueAxes.reduce((value, axis) => {
- if (axis.name.substr(0, axisName.length) === axisName) {
- const num = parseInt(axis.name.substr(axisName.length));
- if (num >= value) value = num + 1;
- }
- return value;
- }, 1);
-
- $scope.editorState.params.valueAxes.push(newAxis);
- return newAxis;
- };
-
- $scope.removeValueAxis = function (axis) {
- if ($scope.editorState.params.valueAxes.length > 1) {
- _.remove($scope.editorState.params.valueAxes, function (valAxis) {
- return valAxis.id === axis.id;
- });
- }
- };
-
- $scope.updateExtents = function (axis) {
- if (!axis.scale.setYExtents) {
- delete axis.scale.min;
- delete axis.scale.max;
- }
- };
-
- $scope.updateBoundsMargin = function (axis) {
- if (!axis.scale.defaultYExtents) {
- delete axis.scale.boundsMargin;
- }
- };
-
- $scope.updateAxisName = function (axis) {
- const axisName = _.capitalize(axis.position) + 'Axis-';
- axis.name = axisName + $scope.editorState.params.valueAxes.reduce((value, axis) => {
- if (axis.name.substr(0, axisName.length) === axisName) {
- const num = parseInt(axis.name.substr(axisName.length));
- if (num >= value) value = num + 1;
- }
- return value;
- }, 1);
- };
-
- const lastCustomLabels = {};
- // We track these so we can know when the agg is changed
- let lastMatchingSeriesAggType = '';
- let lastMatchingSeriesAggField = '';
- $scope.updateAxisTitle = function () {
- $scope.editorState.params.valueAxes.forEach((axis, axisNumber) => {
- let newCustomLabel = '';
- const isFirst = axisNumber === 0;
- const matchingSeries = [];
- $scope.editorState.params.seriesParams.forEach((series, i) => {
- const isMatchingSeries = (isFirst && !series.valueAxis) || (series.valueAxis === axis.id);
- if (isMatchingSeries) {
- let seriesNumber = 0;
- $scope.editorState.aggs.aggs.forEach(agg => {
- if (agg.schema.name === 'metric') {
- if (seriesNumber === i) matchingSeries.push(agg);
- seriesNumber++;
- }
- });
- }
- });
-
- if (matchingSeries.length === 1) {
- newCustomLabel = matchingSeries[0].makeLabel();
- }
-
- const matchingSeriesAggType = _.get(matchingSeries, '[0]type.name', '');
- const matchingSeriesAggField = _.get(matchingSeries, '[0]params.field.name', '');
-
- if (lastCustomLabels[axis.id] !== newCustomLabel && newCustomLabel !== '') {
- const isFirstRender = Object.keys(lastCustomLabels).length === 0;
- const aggTypeIsChanged = lastMatchingSeriesAggType !== matchingSeriesAggType;
- const aggFieldIsChanged = lastMatchingSeriesAggField !== matchingSeriesAggField;
- const aggIsChanged = aggTypeIsChanged || aggFieldIsChanged;
- const axisTitleIsEmpty = axis.title.text === '';
- const lastCustomLabelMatchesAxisTitle = lastCustomLabels[axis.id] === axis.title.text;
-
- if (!isFirstRender && (aggIsChanged || axisTitleIsEmpty || lastCustomLabelMatchesAxisTitle)) {
- axis.title.text = newCustomLabel; // Override axis title with new custom label
- }
-
- lastCustomLabels[axis.id] = newCustomLabel;
- }
-
- lastMatchingSeriesAggType = matchingSeriesAggType;
- lastMatchingSeriesAggField = matchingSeriesAggField;
- });
- };
-
- $scope.$watch(() => {
- return $scope.editorState.aggs.aggs.map(agg => {
- return safeMakeLabel(agg);
- }).join();
- }, () => {
- $scope.updateAxisTitle();
- });
- }
- };
-});
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/editors/__tests__/point_series.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/editors/__tests__/point_series.js
deleted file mode 100644
index f2157496b4649..0000000000000
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/editors/__tests__/point_series.js
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import angular from 'angular';
-import _ from 'lodash';
-import expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import $ from 'jquery';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-import LineVisTypeProvider from '../../line';
-import { VisProvider } from 'ui/vis';
-import { AggConfig } from 'ui/vis/agg_config';
-
-describe('point series editor', function () {
- let $parentScope;
- let $container;
- let $elem;
- let lineVisType;
- let Vis;
- let indexPattern;
-
- function makeConfig() {
- return {
- type: 'line',
- params: lineVisType.visConfig.defaults,
- aggs: [
- { type: 'count', schema: 'metric', params: { field: 'bytes' } },
- { type: 'terms', schema: 'segment', params: { field: 'machine.os' } },
- ],
- listeners: { click: _.noop }
- };
- }
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function ($rootScope, $compile, Private) {
- lineVisType = Private(LineVisTypeProvider);
- Vis = Private(VisProvider);
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- $parentScope = $rootScope;
- $parentScope.vis = new Vis(indexPattern, makeConfig());
- $parentScope.editorState = {
- params: $parentScope.vis.params,
- aggs: $parentScope.vis.aggs,
- };
- $parentScope.savedVis = {};
-
- // share the scope
- //_.defaults($parentScope, $rootScope, Object.getPrototypeOf($rootScope));
-
- $container = $(document.createElement('div'))
- .appendTo('body');
- // make the element
- $elem = angular.element('' +
- '
');
- $container.append($elem);
-
- // compile the html
- $compile($elem)($parentScope);
-
- // Digest everything
- $elem.scope().$digest();
- }));
-
- afterEach(function () {
- $container.remove();
- });
-
- it('should show correct series', function () {
- expect($parentScope.editorState.params.seriesParams.length).to.be(1);
- expect($parentScope.editorState.params.seriesParams[0].data.label).to.be('Count');
- });
-
- it('should update series when new agg is added', function () {
- const aggConfig = new AggConfig($parentScope.vis.aggs, { type: 'avg', schema: 'metric', params: { field: 'bytes' } });
- $parentScope.vis.aggs.aggs.push(aggConfig);
- $parentScope.$digest();
- expect($parentScope.editorState.params.seriesParams.length).to.be(2);
- });
-
- it('should only allow left and right value axis position when category axis is horizontal', function () {
- expect($parentScope.isPositionDisabled('top')).to.be(true);
- expect($parentScope.isPositionDisabled('bottom')).to.be(true);
- expect($parentScope.isPositionDisabled('left')).to.be(false);
- expect($parentScope.isPositionDisabled('right')).to.be(false);
- });
-
- it('should only allow top and bottom value axis position when category axis is vertical', function () {
- $parentScope.editorState.params.categoryAxes[0].position = 'left';
- $parentScope.$digest();
- expect($parentScope.editorState.params.valueAxes[0].position).to.be('bottom');
- expect($parentScope.isPositionDisabled('top')).to.be(false);
- expect($parentScope.isPositionDisabled('bottom')).to.be(false);
- expect($parentScope.isPositionDisabled('left')).to.be(true);
- expect($parentScope.isPositionDisabled('right')).to.be(true);
- });
-
- it('should add value axis', function () {
- $parentScope.addValueAxis();
- expect($parentScope.editorState.params.valueAxes.length).to.be(2);
- });
-
- it('should remove value axis', function () {
- $parentScope.addValueAxis();
- $parentScope.removeValueAxis({ id: 'ValueAxis-2' });
- expect($parentScope.editorState.params.valueAxes.length).to.be(1);
- });
-
- it('should not allow to remove the last value axis', function () {
- $parentScope.removeValueAxis({ id: 'ValueAxis-1' });
- expect($parentScope.editorState.params.valueAxes.length).to.be(1);
- });
-
- it('should set the value axis title if its not set', function () {
- $parentScope.updateAxisTitle();
- expect($parentScope.editorState.params.valueAxes[0].title.text).to.equal('Count');
- });
-
- it('should not update the value axis title if custom title was set', function () {
- $parentScope.editorState.params.valueAxes[0].title.text = 'Custom Title';
- $parentScope.updateAxisTitle();
- expect($parentScope.editorState.params.valueAxes[0].title.text).to.equal('Custom Title');
- });
-
- it('should set the custom title to match the value axis label when only one agg exists for that axis', function () {
- $parentScope.editorState.aggs.aggs[0].params.customLabel = 'Custom Label';
- $parentScope.updateAxisTitle();
- expect($parentScope.editorState.params.valueAxes[0].title.text).to.equal('Custom Label');
- });
-
- it('should not set the custom title to match the value axis label when more than one agg exists for that axis', function () {
- const aggConfig = new AggConfig($parentScope.vis.aggs, { type: 'avg', schema: 'metric', params: { field: 'bytes' } });
- $parentScope.vis.aggs.aggs.push(aggConfig);
- $parentScope.$digest();
- $parentScope.editorState.aggs.aggs[0].params.customLabel = 'Custom Label';
- $parentScope.updateAxisTitle();
- expect($parentScope.editorState.params.valueAxes[0].title.text).to.equal('Count');
- });
-
- it('should not overwrite the custom title with the value axis label if the custom title has been changed', function () {
- $parentScope.editorState.params.valueAxes[0].title.text = 'Custom Title';
- $parentScope.editorState.aggs.aggs[0].params.customLabel = 'Custom Label';
- $parentScope.updateAxisTitle();
- expect($parentScope.editorState.params.valueAxes[0].title.text).to.equal('Custom Title');
- });
-
- it('should overwrite the custom title when the agg type changes', function () {
- const aggConfig = new AggConfig($parentScope.vis.aggs, { type: 'avg', schema: 'metric', params: { field: 'bytes' } });
-
- $parentScope.editorState.params.valueAxes[0].title.text = 'Custom Title';
- $parentScope.editorState.aggs.aggs[0].params.customLabel = 'Custom Label';
- $parentScope.updateAxisTitle();
-
- $parentScope.vis.aggs.aggs.push(aggConfig);
- $parentScope.vis.aggs.aggs.shift();
- $parentScope.$digest();
- $parentScope.updateAxisTitle();
-
- expect($parentScope.editorState.params.valueAxes[0].title.text).to.equal('Average bytes');
- });
-});
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js
index c809f0f024ebd..19960d730005f 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js
@@ -20,12 +20,24 @@
import { VisFactoryProvider } from 'ui/vis/vis_factory';
import { i18n } from '@kbn/i18n';
import { Schemas } from 'ui/vis/editors/default/schemas';
-import { PointSeriesOptions } from './components/options';
-import { getLegendPositions, LegendPositions } from './utils/legend_positions';
+import { AggGroupNames } from 'ui/vis/editors/default';
+import {
+ Positions,
+ ChartTypes,
+ ChartModes,
+ AxisTypes,
+ ScaleTypes,
+ AxisModes,
+ Rotates,
+ ThresholdLineStyles,
+ getConfigCollections,
+} from './utils/collections';
+import { getAreaOptionTabs, getCountLabel } from './utils/common_config';
import { palettes } from '@elastic/eui/lib/services';
export default function PointSeriesVisType(Private) {
const VisFactory = Private(VisFactoryProvider);
+ const countLabel = getCountLabel();
return VisFactory.createVislibVisualization({
name: 'histogram',
@@ -43,12 +55,12 @@ export default function PointSeriesVisType(Private) {
categoryAxes: [
{
id: 'CategoryAxis-1',
- type: 'category',
- position: 'bottom',
+ type: AxisTypes.CATEGORY,
+ position: Positions.BOTTOM,
show: true,
style: {},
scale: {
- type: 'linear'
+ type: ScaleTypes.LINEAR,
},
labels: {
show: true,
@@ -62,42 +74,43 @@ export default function PointSeriesVisType(Private) {
{
id: 'ValueAxis-1',
name: 'LeftAxis-1',
- type: 'value',
- position: 'left',
+ type: AxisTypes.VALUE,
+ position: Positions.LEFT,
show: true,
style: {},
scale: {
- type: 'linear',
- mode: 'normal'
+ type: ScaleTypes.LINEAR,
+ mode: AxisModes.NORMAL,
},
labels: {
show: true,
- rotate: 0,
+ rotate: Rotates.HORIZONTAL,
filter: false,
truncate: 100
},
title: {
- text: 'Count'
+ text: countLabel,
}
}
],
seriesParams: [
{
- show: 'true',
- type: 'histogram',
- mode: 'stacked',
+ show: true,
+ type: ChartTypes.HISTOGRAM,
+ mode: ChartModes.STACKED,
data: {
- label: 'Count',
+ label: countLabel,
id: '1'
},
valueAxis: 'ValueAxis-1',
drawLinesBetweenPoints: true,
+ lineWidth: 2,
showCircles: true
}
],
addTooltip: true,
addLegend: true,
- legendPosition: LegendPositions.RIGHT,
+ legendPosition: Positions.RIGHT,
times: [],
addTimeMarker: false,
labels: {
@@ -107,51 +120,17 @@ export default function PointSeriesVisType(Private) {
show: false,
value: 10,
width: 1,
- style: 'full',
+ style: ThresholdLineStyles.FULL,
color: palettes.euiPaletteColorBlind.colors[9]
}
},
},
editorConfig: {
- collections: {
- legendPositions: getLegendPositions(),
- positions: ['top', 'left', 'right', 'bottom'],
- chartTypes: [{
- value: 'line',
- text: 'line'
- }, {
- value: 'area',
- text: 'area'
- }, {
- value: 'histogram',
- text: 'bar'
- }],
- axisModes: ['normal', 'percentage', 'wiggle', 'silhouette'],
- scaleTypes: ['linear', 'log', 'square root'],
- chartModes: ['normal', 'stacked'],
- interpolationModes: [{
- value: 'linear',
- text: 'straight',
- }, {
- value: 'cardinal',
- text: 'smoothed',
- }, {
- value: 'step-after',
- text: 'stepped',
- }],
- },
- optionTabs: [
- {
- name: 'advanced',
- title: 'Metrics & Axes',
- editor: '' +
- '
'
- },
- { name: 'options', title: 'Panel Settings', editor: PointSeriesOptions },
- ],
+ collections: getConfigCollections(),
+ optionTabs: getAreaOptionTabs(),
schemas: new Schemas([
{
- group: 'metrics',
+ group: AggGroupNames.Metrics,
name: 'metric',
title: i18n.translate('kbnVislibVisTypes.histogram.metricTitle', { defaultMessage: 'Y-axis' }),
min: 1,
@@ -161,7 +140,7 @@ export default function PointSeriesVisType(Private) {
]
},
{
- group: 'metrics',
+ group: AggGroupNames.Metrics,
name: 'radius',
title: i18n.translate('kbnVislibVisTypes.histogram.radiusTitle', { defaultMessage: 'Dot size' }),
min: 0,
@@ -169,7 +148,7 @@ export default function PointSeriesVisType(Private) {
aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality']
},
{
- group: 'buckets',
+ group: AggGroupNames.Buckets,
name: 'segment',
title: i18n.translate('kbnVislibVisTypes.histogram.segmentTitle', { defaultMessage: 'X-axis' }),
min: 0,
@@ -177,7 +156,7 @@ export default function PointSeriesVisType(Private) {
aggFilter: ['!geohash_grid', '!geotile_grid', '!filter']
},
{
- group: 'buckets',
+ group: AggGroupNames.Buckets,
name: 'group',
title: i18n.translate('kbnVislibVisTypes.histogram.groupTitle', { defaultMessage: 'Split series' }),
min: 0,
@@ -185,7 +164,7 @@ export default function PointSeriesVisType(Private) {
aggFilter: ['!geohash_grid', '!geotile_grid', '!filter']
},
{
- group: 'buckets',
+ group: AggGroupNames.Buckets,
name: 'split',
title: i18n.translate('kbnVislibVisTypes.histogram.splitTitle', { defaultMessage: 'Split chart' }),
min: 0,
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js
index 0bb23862e1ebc..eb18bb763aa3d 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js
@@ -20,11 +20,24 @@
import { VisFactoryProvider } from 'ui/vis/vis_factory';
import { i18n } from '@kbn/i18n';
import { Schemas } from 'ui/vis/editors/default/schemas';
-import { PointSeriesOptions } from './components/options';
-import { getLegendPositions, LegendPositions } from './utils/legend_positions';
+import { AggGroupNames } from 'ui/vis/editors/default';
+import {
+ Positions,
+ ChartTypes,
+ ChartModes,
+ AxisTypes,
+ ScaleTypes,
+ AxisModes,
+ Rotates,
+ ThresholdLineStyles,
+ getConfigCollections,
+} from './utils/collections';
+import { getAreaOptionTabs, getCountLabel } from './utils/common_config';
+import { palettes } from '@elastic/eui/lib/services';
export default function PointSeriesVisType(Private) {
const VisFactory = Private(VisFactoryProvider);
+ const countLabel = getCountLabel();
return VisFactory.createVislibVisualization({
name: 'horizontal_bar',
@@ -42,17 +55,17 @@ export default function PointSeriesVisType(Private) {
categoryAxes: [
{
id: 'CategoryAxis-1',
- type: 'category',
- position: 'left',
+ type: AxisTypes.CATEGORY,
+ position: Positions.LEFT,
show: true,
style: {
},
scale: {
- type: 'linear'
+ type: ScaleTypes.LINEAR,
},
labels: {
show: true,
- rotate: 0,
+ rotate: Rotates.HORIZONTAL,
filter: false,
truncate: 200
},
@@ -63,86 +76,60 @@ export default function PointSeriesVisType(Private) {
{
id: 'ValueAxis-1',
name: 'LeftAxis-1',
- type: 'value',
- position: 'bottom',
+ type: AxisTypes.VALUE,
+ position: Positions.BOTTOM,
show: true,
style: {
},
scale: {
- type: 'linear',
- mode: 'normal'
+ type: ScaleTypes.LINEAR,
+ mode: AxisModes.NORMAL,
},
labels: {
show: true,
- rotate: 75,
+ rotate: Rotates.ANGLED,
filter: true,
truncate: 100
},
title: {
- text: 'Count'
+ text: countLabel,
}
}
],
seriesParams: [{
show: true,
- type: 'histogram',
- mode: 'normal',
+ type: ChartTypes.HISTOGRAM,
+ mode: ChartModes.NORMAL,
data: {
- label: 'Count',
+ label: countLabel,
id: '1'
},
valueAxis: 'ValueAxis-1',
drawLinesBetweenPoints: true,
+ lineWidth: 2,
showCircles: true
}],
addTooltip: true,
addLegend: true,
- legendPosition: LegendPositions.RIGHT,
+ legendPosition: Positions.RIGHT,
times: [],
addTimeMarker: false,
labels: {},
+ thresholdLine: {
+ show: false,
+ value: 10,
+ width: 1,
+ style: ThresholdLineStyles.FULL,
+ color: palettes.euiPaletteColorBlind.colors[9]
+ },
},
},
editorConfig: {
- collections: {
- legendPositions: getLegendPositions(),
- positions: ['top', 'left', 'right', 'bottom'],
- chartTypes: [{
- value: 'line',
- text: 'line'
- }, {
- value: 'area',
- text: 'area'
- }, {
- value: 'histogram',
- text: 'bar'
- }],
- axisModes: ['normal', 'percentage', 'wiggle', 'silhouette'],
- scaleTypes: ['linear', 'log', 'square root'],
- chartModes: ['normal', 'stacked'],
- interpolationModes: [{
- value: 'linear',
- text: 'straight',
- }, {
- value: 'cardinal',
- text: 'smoothed',
- }, {
- value: 'step-after',
- text: 'stepped',
- }],
- },
- optionTabs: [
- {
- name: 'advanced',
- title: 'Metrics & Axes',
- editor: '' +
- '
'
- },
- { name: 'options', title: 'Panel Settings', editor: PointSeriesOptions },
- ],
+ collections: getConfigCollections(),
+ optionTabs: getAreaOptionTabs(),
schemas: new Schemas([
{
- group: 'metrics',
+ group: AggGroupNames.Metrics,
name: 'metric',
title: i18n.translate('kbnVislibVisTypes.horizontalBar.metricTitle', { defaultMessage: 'Y-axis' }),
min: 1,
@@ -152,7 +139,7 @@ export default function PointSeriesVisType(Private) {
]
},
{
- group: 'metrics',
+ group: AggGroupNames.Metrics,
name: 'radius',
title: i18n.translate('kbnVislibVisTypes.horizontalBar.radiusTitle', { defaultMessage: 'Dot size' }),
min: 0,
@@ -160,7 +147,7 @@ export default function PointSeriesVisType(Private) {
aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality']
},
{
- group: 'buckets',
+ group: AggGroupNames.Buckets,
name: 'segment',
title: i18n.translate('kbnVislibVisTypes.horizontalBar.segmentTitle', { defaultMessage: 'X-axis' }),
min: 0,
@@ -168,7 +155,7 @@ export default function PointSeriesVisType(Private) {
aggFilter: ['!geohash_grid', '!geotile_grid', '!filter']
},
{
- group: 'buckets',
+ group: AggGroupNames.Buckets,
name: 'group',
title: i18n.translate('kbnVislibVisTypes.horizontalBar.groupTitle', { defaultMessage: 'Split series' }),
min: 0,
@@ -176,7 +163,7 @@ export default function PointSeriesVisType(Private) {
aggFilter: ['!geohash_grid', '!geotile_grid', '!filter']
},
{
- group: 'buckets',
+ group: AggGroupNames.Buckets,
name: 'split',
title: i18n.translate('kbnVislibVisTypes.horizontalBar.splitTitle', { defaultMessage: 'Split chart' }),
min: 0,
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js
index 6358800033399..15b640ebc4c85 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js
@@ -20,13 +20,25 @@
import { VisFactoryProvider } from 'ui/vis/vis_factory';
import { i18n } from '@kbn/i18n';
import { Schemas } from 'ui/vis/editors/default/schemas';
-import { PointSeriesOptions } from './components/options';
-import { getLegendPositions, LegendPositions } from './utils/legend_positions';
+import { AggGroupNames } from 'ui/vis/editors/default';
+import {
+ Positions,
+ ChartTypes,
+ ChartModes,
+ AxisTypes,
+ ScaleTypes,
+ AxisModes,
+ Rotates,
+ ThresholdLineStyles,
+ InterpolationModes,
+ getConfigCollections,
+} from './utils/collections';
import { palettes } from '@elastic/eui/lib/services';
-
+import { getAreaOptionTabs, getCountLabel } from './utils/common_config';
export default function PointSeriesVisType(Private) {
const VisFactory = Private(VisFactoryProvider);
+ const countLabel = getCountLabel();
return VisFactory.createVislibVisualization({
name: 'line',
@@ -42,12 +54,12 @@ export default function PointSeriesVisType(Private) {
categoryAxes: [
{
id: 'CategoryAxis-1',
- type: 'category',
- position: 'bottom',
+ type: AxisTypes.CATEGORY,
+ position: Positions.BOTTOM,
show: true,
style: {},
scale: {
- type: 'linear'
+ type: ScaleTypes.LINEAR,
},
labels: {
show: true,
@@ -61,42 +73,44 @@ export default function PointSeriesVisType(Private) {
{
id: 'ValueAxis-1',
name: 'LeftAxis-1',
- type: 'value',
- position: 'left',
+ type: AxisTypes.VALUE,
+ position: Positions.LEFT,
show: true,
style: {},
scale: {
- type: 'linear',
- mode: 'normal'
+ type: ScaleTypes.LINEAR,
+ mode: AxisModes.NORMAL,
},
labels: {
show: true,
- rotate: 0,
+ rotate: Rotates.HORIZONTAL,
filter: false,
truncate: 100
},
title: {
- text: 'Count'
+ text: countLabel,
}
}
],
seriesParams: [
{
- show: 'true',
- type: 'line',
- mode: 'normal',
+ show: true,
+ type: ChartTypes.LINE,
+ mode: ChartModes.NORMAL,
data: {
- label: 'Count',
+ label: countLabel,
id: '1'
},
valueAxis: 'ValueAxis-1',
drawLinesBetweenPoints: true,
+ lineWidth: 2,
+ interpolate: InterpolationModes.LINEAR,
showCircles: true
}
],
addTooltip: true,
addLegend: true,
- legendPosition: LegendPositions.RIGHT,
+ legendPosition: Positions.RIGHT,
times: [],
addTimeMarker: false,
labels: {},
@@ -104,51 +118,17 @@ export default function PointSeriesVisType(Private) {
show: false,
value: 10,
width: 1,
- style: 'full',
+ style: ThresholdLineStyles.FULL,
color: palettes.euiPaletteColorBlind.colors[9]
}
},
},
editorConfig: {
- collections: {
- legendPositions: getLegendPositions(),
- positions: ['top', 'left', 'right', 'bottom'],
- chartTypes: [{
- value: 'line',
- text: 'line'
- }, {
- value: 'area',
- text: 'area'
- }, {
- value: 'histogram',
- text: 'bar'
- }],
- axisModes: ['normal', 'percentage', 'wiggle', 'silhouette'],
- scaleTypes: ['linear', 'log', 'square root'],
- chartModes: ['normal', 'stacked'],
- interpolationModes: [{
- value: 'linear',
- text: 'straight',
- }, {
- value: 'cardinal',
- text: 'smoothed',
- }, {
- value: 'step-after',
- text: 'stepped',
- }],
- },
- optionTabs: [
- {
- name: 'advanced',
- title: 'Metrics & Axes',
- editor: '' +
- '
'
- },
- { name: 'options', title: 'Panel Settings', editor: PointSeriesOptions },
- ],
+ collections: getConfigCollections(),
+ optionTabs: getAreaOptionTabs(),
schemas: new Schemas([
{
- group: 'metrics',
+ group: AggGroupNames.Metrics,
name: 'metric',
title: i18n.translate('kbnVislibVisTypes.line.metricTitle', { defaultMessage: 'Y-axis' }),
min: 1,
@@ -158,7 +138,7 @@ export default function PointSeriesVisType(Private) {
]
},
{
- group: 'metrics',
+ group: AggGroupNames.Metrics,
name: 'radius',
title: i18n.translate('kbnVislibVisTypes.line.radiusTitle', { defaultMessage: 'Dot size' }),
min: 0,
@@ -166,7 +146,7 @@ export default function PointSeriesVisType(Private) {
aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality', 'top_hits']
},
{
- group: 'buckets',
+ group: AggGroupNames.Buckets,
name: 'segment',
title: i18n.translate('kbnVislibVisTypes.line.segmentTitle', { defaultMessage: 'X-axis' }),
min: 0,
@@ -174,7 +154,7 @@ export default function PointSeriesVisType(Private) {
aggFilter: ['!geohash_grid', '!geotile_grid', '!filter']
},
{
- group: 'buckets',
+ group: AggGroupNames.Buckets,
name: 'group',
title: i18n.translate('kbnVislibVisTypes.line.groupTitle', { defaultMessage: 'Split series' }),
min: 0,
@@ -182,7 +162,7 @@ export default function PointSeriesVisType(Private) {
aggFilter: ['!geohash_grid', '!geotile_grid', '!filter']
},
{
- group: 'buckets',
+ group: AggGroupNames.Buckets,
name: 'split',
title: i18n.translate('kbnVislibVisTypes.line.splitTitle', { defaultMessage: 'Split chart' }),
min: 0,
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/types.ts b/src/legacy/core_plugins/kbn_vislib_vis_types/public/types.ts
index 90bd577828cd8..6cad6e47ce8b3 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/types.ts
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/types.ts
@@ -17,40 +17,77 @@
* under the License.
*/
-import { LegendPositions } from './utils/legend_positions';
+import {
+ Positions,
+ ChartModes,
+ ChartTypes,
+ AxisModes,
+ InterpolationModes,
+ Rotates,
+ ScaleTypes,
+ ThresholdLineStyles,
+} from './utils/collections';
export interface CommonVislibParams {
addTooltip: boolean;
- legendPosition: LegendPositions;
+ legendPosition: Positions;
}
interface Labels {
filter: boolean;
- rotate?: number;
+ rotate?: Rotates;
show: boolean;
- truncate: number;
+ truncate: number | null;
}
+
+export interface Scale {
+ boundsMargin?: number | '';
+ defaultYExtents?: boolean;
+ max?: number | null;
+ min?: number | null;
+ mode?: AxisModes;
+ setYExtents?: boolean;
+ type: ScaleTypes;
+}
+
interface ThresholdLine {
show: boolean;
value: number;
width: number;
- style: 'full' | 'dashed' | 'dot-dashed';
+ style: ThresholdLineStyles;
color: string;
}
-export interface ValueAxis {
+
+export interface Axis {
id: string;
labels: Labels;
- name: string;
- position: LegendPositions;
- scale: { type: string };
+ position: Positions;
+ scale: Scale;
show: boolean;
style: object;
title: { text: string };
type: string;
}
+export interface ValueAxis extends Axis {
+ name: string;
+}
+
+export interface SeriesParam {
+ data: { label: string; id: string };
+ drawLinesBetweenPoints: boolean;
+ interpolate: InterpolationModes;
+ lineWidth?: number;
+ mode: ChartModes;
+ show: boolean;
+ showCircles: boolean;
+ type: ChartTypes;
+ valueAxis: string;
+}
+
export interface BasicVislibParams extends CommonVislibParams {
addTimeMarker: boolean;
+ categoryAxes: Axis[];
orderBucketsBySum?: boolean;
labels: Labels;
thresholdLine: ThresholdLine;
@@ -59,4 +96,5 @@ export interface BasicVislibParams extends CommonVislibParams {
categoryLines: boolean;
valueAxis?: string;
};
+ seriesParams: SeriesParam[];
}
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/collections.ts b/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/collections.ts
new file mode 100644
index 0000000000000..b8300dc42e4b7
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/collections.ts
@@ -0,0 +1,261 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { i18n } from '@kbn/i18n';
+
+export enum Positions {
+ RIGHT = 'right',
+ LEFT = 'left',
+ TOP = 'top',
+ BOTTOM = 'bottom',
+}
+
+const positions = [
+ {
+ text: i18n.translate('kbnVislibVisTypes.legendPositions.topText', {
+ defaultMessage: 'Top',
+ }),
+ value: Positions.TOP,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.legendPositions.leftText', {
+ defaultMessage: 'Left',
+ }),
+ value: Positions.LEFT,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.legendPositions.rightText', {
+ defaultMessage: 'Right',
+ }),
+ value: Positions.RIGHT,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.legendPositions.bottomText', {
+ defaultMessage: 'Bottom',
+ }),
+ value: Positions.BOTTOM,
+ },
+];
+
+export enum ChartTypes {
+ LINE = 'line',
+ AREA = 'area',
+ HISTOGRAM = 'histogram',
+}
+
+const chartTypes = [
+ {
+ text: i18n.translate('kbnVislibVisTypes.chartTypes.lineText', {
+ defaultMessage: 'Line',
+ }),
+ value: ChartTypes.LINE,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.chartTypes.areaText', {
+ defaultMessage: 'Area',
+ }),
+ value: ChartTypes.AREA,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.chartTypes.barText', {
+ defaultMessage: 'Bar',
+ }),
+ value: ChartTypes.HISTOGRAM,
+ },
+];
+
+export enum ChartModes {
+ NORMAL = 'normal',
+ STACKED = 'stacked',
+}
+
+const chartModes = [
+ {
+ text: i18n.translate('kbnVislibVisTypes.chartModes.normalText', {
+ defaultMessage: 'Normal',
+ }),
+ value: ChartModes.NORMAL,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.chartModes.stackedText', {
+ defaultMessage: 'Stacked',
+ }),
+ value: ChartModes.STACKED,
+ },
+];
+
+export enum InterpolationModes {
+ LINEAR = 'linear',
+ CARDINAL = 'cardinal',
+ STEP_AFTER = 'step-after',
+}
+
+const interpolationModes = [
+ {
+ text: i18n.translate('kbnVislibVisTypes.interpolationModes.straightText', {
+ defaultMessage: 'Straight',
+ }),
+ value: InterpolationModes.LINEAR,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.interpolationModes.smoothedText', {
+ defaultMessage: 'Smoothed',
+ }),
+ value: InterpolationModes.CARDINAL,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.interpolationModes.steppedText', {
+ defaultMessage: 'Stepped',
+ }),
+ value: InterpolationModes.STEP_AFTER,
+ },
+];
+
+export enum AxisTypes {
+ CATEGORY = 'category',
+ VALUE = 'value',
+}
+
+export enum ScaleTypes {
+ LINEAR = 'linear',
+ LOG = 'log',
+ SQUARE_ROOT = 'square root',
+}
+
+const scaleTypes = [
+ {
+ text: i18n.translate('kbnVislibVisTypes.scaleTypes.linearText', {
+ defaultMessage: 'Linear',
+ }),
+ value: ScaleTypes.LINEAR,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.scaleTypes.logText', {
+ defaultMessage: 'Log',
+ }),
+ value: ScaleTypes.LOG,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.scaleTypes.squareRootText', {
+ defaultMessage: 'Square root',
+ }),
+ value: ScaleTypes.SQUARE_ROOT,
+ },
+];
+
+export enum AxisModes {
+ NORMAL = 'normal',
+ PERCENTAGE = 'percentage',
+ WIGGLE = 'wiggle',
+ SILHOUETTE = 'silhouette',
+}
+
+const axisModes = [
+ {
+ text: i18n.translate('kbnVislibVisTypes.axisModes.normalText', {
+ defaultMessage: 'Normal',
+ }),
+ value: AxisModes.NORMAL,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.axisModes.percentageText', {
+ defaultMessage: 'Percentage',
+ }),
+ value: AxisModes.PERCENTAGE,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.axisModes.wiggleText', {
+ defaultMessage: 'Wiggle',
+ }),
+ value: AxisModes.WIGGLE,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.axisModes.silhouetteText', {
+ defaultMessage: 'Silhouette',
+ }),
+ value: AxisModes.SILHOUETTE,
+ },
+];
+
+export enum Rotates {
+ HORIZONTAL = 0,
+ VERTICAL = 90,
+ ANGLED = 75,
+}
+
+export enum ThresholdLineStyles {
+ FULL = 'full',
+ DASHED = 'dashed',
+ DOT_DASHED = 'dot-dashed',
+}
+
+const thresholdLineStyles = [
+ {
+ value: ThresholdLineStyles.FULL,
+ text: i18n.translate('kbnVislibVisTypes.thresholdLine.style.fullText', {
+ defaultMessage: 'Full',
+ }),
+ },
+ {
+ value: ThresholdLineStyles.DASHED,
+ text: i18n.translate('kbnVislibVisTypes.thresholdLine.style.dashedText', {
+ defaultMessage: 'Dashed',
+ }),
+ },
+ {
+ value: ThresholdLineStyles.DOT_DASHED,
+ text: i18n.translate('kbnVislibVisTypes.thresholdLine.style.dotdashedText', {
+ defaultMessage: 'Dot-dashed',
+ }),
+ },
+];
+
+const rotateOptions = [
+ {
+ text: i18n.translate('kbnVislibVisTypes.categoryAxis.rotate.horizontalText', {
+ defaultMessage: 'Horizontal',
+ }),
+ value: Rotates.HORIZONTAL,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.categoryAxis.rotate.verticalText', {
+ defaultMessage: 'Vertical',
+ }),
+ value: Rotates.VERTICAL,
+ },
+ {
+ text: i18n.translate('kbnVislibVisTypes.categoryAxis.rotate.angledText', {
+ defaultMessage: 'Angled',
+ }),
+ value: Rotates.ANGLED,
+ },
+];
+
+const getConfigCollections = () => ({
+ legendPositions: positions,
+ positions,
+ chartTypes,
+ axisModes,
+ scaleTypes,
+ chartModes,
+ interpolationModes,
+ thresholdLineStyles,
+});
+
+export { getConfigCollections, rotateOptions };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/common_config.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/common_config.tsx
new file mode 100644
index 0000000000000..fdec24a002c07
--- /dev/null
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/common_config.tsx
@@ -0,0 +1,54 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { VisOptionsProps } from 'ui/vis/editors/default';
+import { i18n } from '@kbn/i18n';
+import { PointSeriesOptions, MetricsAxisOptions } from '../components/options';
+import { ValidationWrapper } from '../components/common';
+import { BasicVislibParams } from '../types';
+
+function getAreaOptionTabs() {
+ return [
+ {
+ name: 'advanced',
+ title: i18n.translate('kbnVislibVisTypes.area.tabs.metricsAxesTitle', {
+ defaultMessage: 'Metrics & axes',
+ }),
+ editor: (props: VisOptionsProps) => (
+
+ ),
+ },
+ {
+ name: 'options',
+ title: i18n.translate('kbnVislibVisTypes.area.tabs.panelSettingsTitle', {
+ defaultMessage: 'Panel settings',
+ }),
+ editor: PointSeriesOptions,
+ },
+ ];
+}
+
+function getCountLabel() {
+ return i18n.translate('kbnVislibVisTypes.area.countText', {
+ defaultMessage: 'Count',
+ });
+}
+
+export { getAreaOptionTabs, getCountLabel };
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/legend_positions.ts b/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/legend_positions.ts
deleted file mode 100644
index ffe70eba19b39..0000000000000
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/legend_positions.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { i18n } from '@kbn/i18n';
-
-export enum LegendPositions {
- RIGHT = 'right',
- LEFT = 'left',
- TOP = 'top',
- BOTTOM = 'bottom',
-}
-
-const getLegendPositions = () => [
- {
- text: i18n.translate('kbnVislibVisTypes.legendPositions.topText', {
- defaultMessage: 'Top',
- }),
- value: LegendPositions.TOP,
- },
- {
- text: i18n.translate('kbnVislibVisTypes.legendPositions.leftText', {
- defaultMessage: 'Left',
- }),
- value: LegendPositions.LEFT,
- },
- {
- text: i18n.translate('kbnVislibVisTypes.legendPositions.rightText', {
- defaultMessage: 'Right',
- }),
- value: LegendPositions.RIGHT,
- },
- {
- text: i18n.translate('kbnVislibVisTypes.legendPositions.bottomText', {
- defaultMessage: 'Bottom',
- }),
- value: LegendPositions.BOTTOM,
- },
-];
-
-export { getLegendPositions };
diff --git a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx
index 56742eaec5203..9749c7fa8e2f9 100644
--- a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx
+++ b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx
@@ -200,6 +200,7 @@ function RegionMapOptions(props: RegionMapOptionsProps) {
label={i18n.translate('regionMap.visParams.outlineWeightLabel', {
defaultMessage: 'Border thickness',
})}
+ min={0}
paramName="outlineWeight"
value={stateParams.outlineWeight}
setValue={setValue}
diff --git a/src/legacy/ui/public/vis/editors/default/_sidebar.scss b/src/legacy/ui/public/vis/editors/default/_sidebar.scss
index 4efee6168a0f8..5d0026ec3d884 100644
--- a/src/legacy/ui/public/vis/editors/default/_sidebar.scss
+++ b/src/legacy/ui/public/vis/editors/default/_sidebar.scss
@@ -165,11 +165,6 @@
margin-left: $euiSizeS;
}
-.visEditorSidebar__collapsibleTitleDescription {
- flex: 1 1 0;
- @include euiTextTruncate;
-}
-
//
// FORMS
//
@@ -183,11 +178,6 @@
@include __legacySelectStyles__bad;
}
-.visEditorSidebar__formTitle {
- @include euiTitle('xxs');
- margin: $euiSizeS 0;
-}
-
.visEditorSidebar__formRow {
display: flex;
align-items: center;
diff --git a/src/legacy/ui/public/vis/editors/default/agg_group.js b/src/legacy/ui/public/vis/editors/default/agg_group.js
index 5a683454a9c1a..e99c8dea3a91d 100644
--- a/src/legacy/ui/public/vis/editors/default/agg_group.js
+++ b/src/legacy/ui/public/vis/editors/default/agg_group.js
@@ -40,6 +40,7 @@ uiModules
'groupName',
'formIsTouched',
'lastParentPipelineAggTitle',
+ 'currentTab',
])
)
.directive('visEditorAggGroup', function () {
@@ -50,6 +51,7 @@ uiModules
template: function () {
return `