Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Infra UI] Add UI to customize Metrics Explorer chart style #41022

Merged
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@ import { MetricsExplorerSeries } from '../../../server/routes/metrics_explorer/t
import {
MetricsExplorerOptions,
MetricsExplorerTimeOptions,
MetricsExplorerYAxisMode,
MetricsExplorerChartOptions,
} from '../../containers/metrics_explorer/use_metrics_explorer_options';
import euiStyled from '../../../../../common/eui_styled_components';
import { createFormatterForMetric } from './helpers/create_formatter_for_metric';
import { MetricLineSeries } from './line_series';
import { MetricExplorerSeriesChart } from './series_chart';
import { MetricsExplorerChartContextMenu } from './chart_context_menu';
import { SourceQuery } from '../../graphql/types';
import { MetricsExplorerEmptyChart } from './empty_chart';
import { MetricsExplorerNoMetrics } from './no_metrics';
import { getChartTheme } from './helpers/get_chart_theme';
import { calculateDomain } from './helpers/calculate_domain';

interface Props {
intl: InjectedIntl;
Expand All @@ -33,6 +36,7 @@ interface Props {
width?: number | string;
height?: number | string;
options: MetricsExplorerOptions;
chartOptions: MetricsExplorerChartOptions;
series: MetricsExplorerSeries;
source: SourceQuery.Query['source']['configuration'] | undefined;
timeRange: MetricsExplorerTimeOptions;
Expand All @@ -45,6 +49,7 @@ export const MetricsExplorerChart = injectUICapabilities(
({
source,
options,
chartOptions,
series,
title,
onFilter,
Expand All @@ -66,6 +71,11 @@ export const MetricsExplorerChart = injectUICapabilities(
[series.rows]
);
const yAxisFormater = useCallback(createFormatterForMetric(first(metrics)), [options]);
const dataDomain = calculateDomain(series, metrics, chartOptions.stack);
const domain =
chartOptions.yAxisMode === MetricsExplorerYAxisMode.fromZero
? { ...dataDomain, min: 0 }
: dataDomain;
return (
<div style={{ padding: 24 }}>
{options.groupBy ? (
Expand All @@ -80,6 +90,7 @@ export const MetricsExplorerChart = injectUICapabilities(
<MetricsExplorerChartContextMenu
timeRange={timeRange}
options={options}
chartOptions={chartOptions}
series={series}
onFilter={onFilter}
source={source}
Expand All @@ -93,6 +104,7 @@ export const MetricsExplorerChart = injectUICapabilities(
<EuiFlexItem grow={false}>
<MetricsExplorerChartContextMenu
options={options}
chartOptions={chartOptions}
series={series}
source={source}
timeRange={timeRange}
Expand All @@ -105,7 +117,14 @@ export const MetricsExplorerChart = injectUICapabilities(
{series.rows.length > 0 ? (
<Chart>
{metrics.map((metric, id) => (
<MetricLineSeries key={id} metric={metric} id={id} series={series} />
<MetricExplorerSeriesChart
type={chartOptions.type}
key={id}
metric={metric}
id={id}
series={series}
stack={chartOptions.stack}
/>
))}
<Axis
id={getAxisId('timestamp')}
Expand All @@ -117,6 +136,7 @@ export const MetricsExplorerChart = injectUICapabilities(
id={getAxisId('values')}
position={Position.Left}
tickFormat={yAxisFormater}
domain={domain}
/>
<Settings onBrushEnd={handleTimeChange} theme={getChartTheme()} />
</Chart>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import React from 'react';
import { MetricsExplorerChartContextMenu, createNodeDetailLink } from './chart_context_menu';
import { mountWithIntl } from '../../utils/enzyme_helpers';
import { options, source, timeRange } from '../../utils/fixtures/metrics_explorer';
import { options, source, timeRange, chartOptions } from '../../utils/fixtures/metrics_explorer';
import { UICapabilities } from 'ui/capabilities';
import { InfraNodeType } from '../../graphql/types';
import DateMath from '@elastic/datemath';
Expand Down Expand Up @@ -37,6 +37,7 @@ describe('MetricsExplorerChartContextMenu', () => {
options={options}
onFilter={onFilter}
uiCapabilities={uiCapabilities}
chartOptions={chartOptions}
/>
);

Expand All @@ -57,6 +58,7 @@ describe('MetricsExplorerChartContextMenu', () => {
options={customOptions}
onFilter={onFilter}
uiCapabilities={uiCapabilities}
chartOptions={chartOptions}
/>
);
component.find('button').simulate('click');
Expand All @@ -71,6 +73,7 @@ describe('MetricsExplorerChartContextMenu', () => {
series={series}
options={options}
uiCapabilities={uiCapabilities}
chartOptions={chartOptions}
/>
);

Expand All @@ -89,6 +92,7 @@ describe('MetricsExplorerChartContextMenu', () => {
options={customOptions}
onFilter={onFilter}
uiCapabilities={uiCapabilities}
chartOptions={chartOptions}
/>
);

Expand All @@ -105,6 +109,7 @@ describe('MetricsExplorerChartContextMenu', () => {
series={series}
options={customOptions}
uiCapabilities={uiCapabilities}
chartOptions={chartOptions}
/>
);

Expand All @@ -125,6 +130,7 @@ describe('MetricsExplorerChartContextMenu', () => {
options={options}
onFilter={onFilter}
uiCapabilities={customUICapabilities}
chartOptions={chartOptions}
/>
);

Expand All @@ -144,6 +150,7 @@ describe('MetricsExplorerChartContextMenu', () => {
options={customOptions}
onFilter={onFilter}
uiCapabilities={customUICapabilities}
chartOptions={chartOptions}
/>
);
expect(component.find('button').length).toBe(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { MetricsExplorerSeries } from '../../../server/routes/metrics_explorer/t
import {
MetricsExplorerOptions,
MetricsExplorerTimeOptions,
MetricsExplorerChartOptions,
} from '../../containers/metrics_explorer/use_metrics_explorer_options';
import { createTSVBLink } from './helpers/create_tsvb_link';
import { InfraNodeType } from '../../graphql/types';
Expand All @@ -31,6 +32,7 @@ interface Props {
source?: SourceConfiguration;
timeRange: MetricsExplorerTimeOptions;
uiCapabilities: UICapabilities;
chartOptions: MetricsExplorerChartOptions;
}

const fieldToNodeType = (source: SourceConfiguration, field: string): InfraNodeType | undefined => {
Expand Down Expand Up @@ -66,7 +68,7 @@ export const createNodeDetailLink = (
};

export const MetricsExplorerChartContextMenu = injectI18n(
({ intl, onFilter, options, series, source, timeRange, uiCapabilities }: Props) => {
({ intl, onFilter, options, series, source, timeRange, uiCapabilities, chartOptions }: Props) => {
const [isPopoverOpen, setPopoverState] = useState(false);
const supportFiltering = options.groupBy != null && onFilter != null;
const handleFilter = useCallback(() => {
Expand All @@ -78,7 +80,7 @@ export const MetricsExplorerChartContextMenu = injectI18n(
setPopoverState(false);
}, [supportFiltering, options.groupBy, series.id, onFilter]);

const tsvbUrl = createTSVBLink(source, options, series, timeRange);
const tsvbUrl = createTSVBLink(source, options, series, timeRange, chartOptions);

// Only display the "Add Filter" option if it's supported
const filterByItem = supportFiltering
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React, { useState, useCallback } from 'react';
import { InjectedIntl, injectI18n, FormattedMessage } from '@kbn/i18n/react';
import {
EuiRadioGroup,
EuiButtonEmpty,
EuiPopover,
EuiForm,
EuiFormRow,
EuiSwitch,
} from '@elastic/eui';
import {
MetricsExplorerChartOptions as ChartOptions,
MetricsExplorerYAxisMode,
MetricsExplorerChartType,
} from '../../containers/metrics_explorer/use_metrics_explorer_options';

interface Props {
chartOptions: ChartOptions;
onChange: (options: ChartOptions) => void;
intl: InjectedIntl;
}

export const MetricsExplorerChartOptions = injectI18n(({ chartOptions, onChange, intl }: Props) => {
const [isPopoverOpen, setPopoverState] = useState<boolean>(false);

const handleClosePopover = useCallback(() => {
setPopoverState(false);
}, []);

const handleOpenPopover = useCallback(() => {
setPopoverState(true);
}, []);

const button = (
<EuiButtonEmpty iconSide="left" iconType="eye" onClick={handleOpenPopover}>
<FormattedMessage
id="xpack.infra.metricsExplorer.customizeChartOptions"
defaultMessage="Customize"
/>
</EuiButtonEmpty>
);

const yAxisRadios = [
{
id: MetricsExplorerYAxisMode.auto,
label: intl.formatMessage({
id: 'xpack.infra.metricsExplorer.chartOptions.autoLabel',
defaultMessage: 'Automatic (Min to Max)',
}),
},
{
id: MetricsExplorerYAxisMode.fromZero,
label: intl.formatMessage({
id: 'xpack.infra.metricsExplorer.chartOptions.fromZeroLabel',
defaultMessage: 'From Zero (0 to Max)',
}),
},
];

const typeRadios = [
{
id: MetricsExplorerChartType.line,
label: intl.formatMessage({
id: 'xpack.infra.metricsExplorer.chartOptions.lineLabel',
defaultMessage: 'Line',
}),
},
{
id: MetricsExplorerChartType.area,
label: intl.formatMessage({
id: 'xpack.infra.metricsExplorer.chartOptions.areaLabel',
defaultMessage: 'Area',
}),
},
];

const handleYAxisChange = useCallback(
(id: string) => {
onChange({
...chartOptions,
yAxisMode: id as MetricsExplorerYAxisMode,
});
},
[chartOptions, onChange]
);

const handleTypeChange = useCallback(
(id: string) => {
onChange({
...chartOptions,
type: id as MetricsExplorerChartType,
});
},
[chartOptions, onChange]
);

const handleStackChange = useCallback(
e => {
onChange({
...chartOptions,
stack: e.target.checked,
});
},
[chartOptions, onChange]
);

return (
<EuiPopover
id="MetricExplorerChartOptionsPopover"
button={button}
isOpen={isPopoverOpen}
closePopover={handleClosePopover}
>
<EuiForm>
<EuiFormRow
compressed
label={intl.formatMessage({
id: 'xpack.infra.metricsExplorer.chartOptions.typeLabel',
defaultMessage: 'Chart Style',
})}
>
<EuiRadioGroup
options={typeRadios}
idSelected={chartOptions.type}
onChange={handleTypeChange}
/>
</EuiFormRow>
<EuiFormRow
compressed
label={intl.formatMessage({
id: 'xpack.infra.metricsExplorer.chartOptions.stackLabel',
defaultMessage: 'Stack Series',
})}
>
<EuiSwitch
label={intl.formatMessage({
id: 'xpack.infra.metricsExplorer.chartOptions.stackSwitchLabel',
defaultMessage: 'Stack',
})}
checked={chartOptions.stack}
onChange={handleStackChange}
/>
</EuiFormRow>
<EuiFormRow
compressed
label={intl.formatMessage({
id: 'xpack.infra.metricsExplorer.chartOptions.yAxisDomainLabel',
defaultMessage: 'Y Axis Domain',
})}
>
<EuiRadioGroup
options={yAxisRadios}
idSelected={chartOptions.yAxisMode}
onChange={handleYAxisChange}
/>
</EuiFormRow>
</EuiForm>
</EuiPopover>
);
});
Loading