[Observability] [Exploratory View] limit breakdown to one series (#113888) (#114845)

* observability - exploratory view - limit breakdown to one series

* adjust content

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Dominique Clarke 2021-10-13 14:31:20 -04:00 committed by GitHub
parent 587f66a604
commit d4f8b4b42e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 13 deletions

View file

@ -6,15 +6,17 @@
*/
import React, { useEffect } from 'react';
import { act, renderHook } from '@testing-library/react-hooks';
import { Route, Router } from 'react-router-dom';
import { render } from '@testing-library/react';
import { UrlStorageContextProvider, useSeriesStorage } from './use_series_storage';
import { getHistoryFromUrl } from '../rtl_helpers';
import type { AppDataType } from '../types';
const mockSingleSeries = [
{
name: 'performance-distribution',
dataType: 'ux',
dataType: 'ux' as AppDataType,
breakdown: 'user_agent.name',
time: { from: 'now-15m', to: 'now' },
},
@ -23,13 +25,13 @@ const mockSingleSeries = [
const mockMultipleSeries = [
{
name: 'performance-distribution',
dataType: 'ux',
dataType: 'ux' as AppDataType,
breakdown: 'user_agent.name',
time: { from: 'now-15m', to: 'now' },
},
{
name: 'kpi-over-time',
dataType: 'synthetics',
dataType: 'synthetics' as AppDataType,
breakdown: 'user_agent.name',
time: { from: 'now-15m', to: 'now' },
},
@ -92,7 +94,7 @@ describe('userSeriesStorage', function () {
);
});
it('should return expected result when there are multiple series series', function () {
it('should return expected result when there are multiple series', function () {
const setData = setupTestComponent(mockMultipleSeries);
expect(setData).toHaveBeenCalledTimes(2);
@ -133,4 +135,41 @@ describe('userSeriesStorage', function () {
})
);
});
it('ensures that only one series has a breakdown', () => {
function wrapper({ children }: { children: React.ReactElement }) {
return (
<UrlStorageContextProvider
storage={{
get: jest
.fn()
.mockImplementation((key: string) => (key === 'sr' ? mockMultipleSeries : null)),
set: jest.fn(),
}}
>
{children}
</UrlStorageContextProvider>
);
}
const { result } = renderHook(() => useSeriesStorage(), { wrapper });
act(() => {
result.current.setSeries(1, mockMultipleSeries[1]);
});
expect(result.current.allSeries).toEqual([
{
name: 'performance-distribution',
dataType: 'ux',
breakdown: 'user_agent.name',
time: { from: 'now-15m', to: 'now' },
},
{
name: 'kpi-over-time',
dataType: 'synthetics',
breakdown: undefined,
time: { from: 'now-15m', to: 'now' },
},
]);
});
});

View file

@ -71,9 +71,16 @@ export function UrlStorageContextProvider({
const setSeries = useCallback((seriesIndex: number, newValue: SeriesUrl) => {
setAllSeries((prevAllSeries) => {
const seriesWithCurrentBreakdown = prevAllSeries.findIndex((series) => series.breakdown);
const newStateRest = prevAllSeries.map((series, index) => {
if (index === seriesIndex) {
return newValue;
return {
...newValue,
breakdown:
seriesWithCurrentBreakdown === seriesIndex || seriesWithCurrentBreakdown === -1
? newValue.breakdown
: undefined,
};
}
return series;
});

View file

@ -55,4 +55,24 @@ describe('Breakdowns', function () {
});
expect(setSeries).toHaveBeenCalledTimes(1);
});
it('should disable breakdowns when a different series has a breakdown', function () {
const initSeries = {
data: [mockUxSeries, { ...mockUxSeries, breakdown: undefined }],
breakdown: USER_AGENT_OS,
};
render(
<Breakdowns
seriesId={1}
seriesConfig={dataViewSeries}
series={{ ...mockUxSeries, breakdown: undefined }}
/>,
{ initSeries }
);
const button = screen.getByText('No breakdown');
expect(button).toHaveAttribute('disabled');
});
});

View file

@ -6,7 +6,8 @@
*/
import React from 'react';
import { EuiSuperSelect } from '@elastic/eui';
import styled from 'styled-components';
import { EuiSuperSelect, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useSeriesStorage } from '../../hooks/use_series_storage';
import { LABEL_FIELDS_BREAKDOWN, USE_BREAK_DOWN_COLUMN } from '../../configurations/constants';
@ -19,7 +20,14 @@ interface Props {
}
export function Breakdowns({ seriesConfig, seriesId, series }: Props) {
const { setSeries } = useSeriesStorage();
const { setSeries, allSeries } = useSeriesStorage();
const indexOfSeriesWithBreakdown = allSeries.findIndex((seriesT) => {
return Boolean(seriesT.breakdown);
});
const currentSeriesHasBreakdown = indexOfSeriesWithBreakdown === seriesId;
const anySeriesHasBreakdown = indexOfSeriesWithBreakdown !== -1;
const differentSeriesHasBreakdown = anySeriesHasBreakdown && !currentSeriesHasBreakdown;
const selectedBreakdown = series.breakdown;
const NO_BREAKDOWN = 'no_breakdown';
@ -69,13 +77,28 @@ export function Breakdowns({ seriesConfig, seriesId, series }: Props) {
valueOfSelected = LABEL_FIELDS_BREAKDOWN;
}
function Select() {
return (
<EuiSuperSelect
options={options}
valueOfSelected={valueOfSelected}
onChange={(value) => onOptionChange(value)}
data-test-subj={'seriesBreakdown'}
disabled={differentSeriesHasBreakdown}
/>
);
}
return (
<EuiSuperSelect
options={options}
valueOfSelected={valueOfSelected}
onChange={(value) => onOptionChange(value)}
data-test-subj={'seriesBreakdown'}
/>
<Wrapper>
{differentSeriesHasBreakdown ? (
<EuiToolTip content={BREAKDOWN_WARNING} position="top">
<Select />
</EuiToolTip>
) : (
<Select />
)}
</Wrapper>
);
}
@ -85,3 +108,13 @@ export const NO_BREAK_DOWN_LABEL = i18n.translate(
defaultMessage: 'No breakdown',
}
);
export const BREAKDOWN_WARNING = i18n.translate('xpack.observability.exp.breakDownFilter.warning', {
defaultMessage: 'Breakdowns can be applied to only one series at a time.',
});
const Wrapper = styled.span`
.euiToolTipAnchor {
width: 100%;
}
`;