Skip to content

Commit

Permalink
Fixes 36818 - Metrics Explorer action menu to honor uiCapabilities (#…
Browse files Browse the repository at this point in the history
…36824)

* Fixes 36818 - Metrics Explorer action menu to honor uiCapabilities

* making test description clearer

* Fixing uiCapabilities
  • Loading branch information
simianhacker authored Jun 21, 2019
1 parent 98f7c75 commit 2f029e6
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { EuiTitle, EuiToolTip, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { Axis, Chart, getAxisId, niceTimeFormatter, Position, Settings } from '@elastic/charts';
import { first, last } from 'lodash';
import moment from 'moment';
import { UICapabilities } from 'ui/capabilities';
import { injectUICapabilities } from 'ui/capabilities/react';
import { MetricsExplorerSeries } from '../../../server/routes/metrics_explorer/types';
import {
MetricsExplorerOptions,
Expand All @@ -35,86 +37,96 @@ interface Props {
source: SourceQuery.Query['source']['configuration'] | undefined;
timeRange: MetricsExplorerTimeOptions;
onTimeChange: (start: string, end: string) => void;
uiCapabilities: UICapabilities;
}

export const MetricsExplorerChart = injectI18n(
({
source,
options,
series,
title,
onFilter,
height = 200,
width = '100%',
timeRange,
onTimeChange,
}: Props) => {
const { metrics } = options;
const handleTimeChange = (from: number, to: number) => {
onTimeChange(moment(from).toISOString(), moment(to).toISOString());
};
const dateFormatter = useCallback(
niceTimeFormatter([first(series.rows).timestamp, last(series.rows).timestamp]),
[series, series.rows]
);
const yAxisFormater = useCallback(createFormatterForMetric(first(metrics)), [options]);
return (
<React.Fragment>
{options.groupBy ? (
<EuiTitle size="xs">
<EuiFlexGroup alignItems="center">
<ChartTitle>
<EuiToolTip content={title}>
<span>{title}</span>
</EuiToolTip>
</ChartTitle>
export const MetricsExplorerChart = injectUICapabilities(
injectI18n(
({
source,
options,
series,
title,
onFilter,
height = 200,
width = '100%',
timeRange,
onTimeChange,
uiCapabilities,
}: Props) => {
const { metrics } = options;
const handleTimeChange = (from: number, to: number) => {
onTimeChange(moment(from).toISOString(), moment(to).toISOString());
};
const dateFormatter = useCallback(
niceTimeFormatter([first(series.rows).timestamp, last(series.rows).timestamp]),
[series, series.rows]
);
const yAxisFormater = useCallback(createFormatterForMetric(first(metrics)), [options]);
return (
<React.Fragment>
{options.groupBy ? (
<EuiTitle size="xs">
<EuiFlexGroup alignItems="center">
<ChartTitle>
<EuiToolTip content={title}>
<span>{title}</span>
</EuiToolTip>
</ChartTitle>
<EuiFlexItem grow={false}>
<MetricsExplorerChartContextMenu
timeRange={timeRange}
options={options}
series={series}
onFilter={onFilter}
source={source}
uiCapabilities={uiCapabilities}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiTitle>
) : (
<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<MetricsExplorerChartContextMenu
timeRange={timeRange}
options={options}
series={series}
onFilter={onFilter}
source={source}
timeRange={timeRange}
uiCapabilities={uiCapabilities}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiTitle>
) : (
<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<MetricsExplorerChartContextMenu
options={options}
series={series}
source={source}
timeRange={timeRange}
/>
</EuiFlexItem>
</EuiFlexGroup>
)}
<div style={{ height, width }}>
{series.rows.length > 0 ? (
<Chart>
{metrics.map((metric, id) => (
<MetricLineSeries key={id} metric={metric} id={id} series={series} />
))}
<Axis
id={getAxisId('timestamp')}
position={Position.Bottom}
showOverlappingTicks={true}
tickFormat={dateFormatter}
/>
<Axis id={getAxisId('values')} position={Position.Left} tickFormat={yAxisFormater} />
<Settings onBrushEnd={handleTimeChange} theme={getChartTheme()} />
</Chart>
) : options.metrics.length > 0 ? (
<MetricsExplorerEmptyChart />
) : (
<MetricsExplorerNoMetrics />
)}
</div>
</React.Fragment>
);
}
<div style={{ height, width }}>
{series.rows.length > 0 ? (
<Chart>
{metrics.map((metric, id) => (
<MetricLineSeries key={id} metric={metric} id={id} series={series} />
))}
<Axis
id={getAxisId('timestamp')}
position={Position.Bottom}
showOverlappingTicks={true}
tickFormat={dateFormatter}
/>
<Axis
id={getAxisId('values')}
position={Position.Left}
tickFormat={yAxisFormater}
/>
<Settings onBrushEnd={handleTimeChange} theme={getChartTheme()} />
</Chart>
) : options.metrics.length > 0 ? (
<MetricsExplorerEmptyChart />
) : (
<MetricsExplorerNoMetrics />
)}
</div>
</React.Fragment>
);
}
)
);

const ChartTitle = euiStyled.div`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ 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 { UICapabilities } from 'ui/capabilities';
import { InfraNodeType } from '../../graphql/types';
import DateMath from '@elastic/datemath';
import { ReactWrapper } from 'enzyme';

const series = { id: 'exmaple-01', rows: [], columns: [] };
const uiCapabilities: UICapabilities = {
navLinks: { show: false },
management: { fake: { show: false } },
catalogue: { show: false },
visualize: { show: true },
};

const getTestSubject = (component: ReactWrapper, name: string) => {
return component.find(`[data-test-subj="${name}"]`).hostNodes();
Expand All @@ -29,6 +36,7 @@ describe('MetricsExplorerChartContextMenu', () => {
series={series}
options={options}
onFilter={onFilter}
uiCapabilities={uiCapabilities}
/>
);

Expand All @@ -48,9 +56,9 @@ describe('MetricsExplorerChartContextMenu', () => {
series={series}
options={customOptions}
onFilter={onFilter}
uiCapabilities={uiCapabilities}
/>
);

component.find('button').simulate('click');
expect(getTestSubject(component, 'metricsExplorerAction-ViewNodeMetrics').length).toBe(0);
});
Expand All @@ -62,6 +70,7 @@ describe('MetricsExplorerChartContextMenu', () => {
source={source}
series={series}
options={options}
uiCapabilities={uiCapabilities}
/>
);

Expand All @@ -79,6 +88,7 @@ describe('MetricsExplorerChartContextMenu', () => {
series={series}
options={customOptions}
onFilter={onFilter}
uiCapabilities={uiCapabilities}
/>
);

Expand All @@ -94,6 +104,7 @@ describe('MetricsExplorerChartContextMenu', () => {
source={source}
series={series}
options={customOptions}
uiCapabilities={uiCapabilities}
/>
);

Expand All @@ -102,6 +113,41 @@ describe('MetricsExplorerChartContextMenu', () => {
getTestSubject(component, 'metricsExplorerAction-OpenInTSVB').prop('disabled')
).toBeTruthy();
});

it('should not display "Open in Visualize" when unavailble in uiCapabilities', async () => {
const customUICapabilities = { ...uiCapabilities, visualize: { show: false } };
const onFilter = jest.fn().mockImplementation((query: string) => void 0);
const component = mountWithIntl(
<MetricsExplorerChartContextMenu
timeRange={timeRange}
source={source}
series={series}
options={options}
onFilter={onFilter}
uiCapabilities={customUICapabilities}
/>
);

component.find('button').simulate('click');
expect(getTestSubject(component, 'metricsExplorerAction-OpenInTSVB').length).toBe(0);
});

it('should not display anything when Visualize is disabled and there are no group bys.', async () => {
const customUICapabilities = { ...uiCapabilities, visualize: { show: false } };
const onFilter = jest.fn().mockImplementation((query: string) => void 0);
const customOptions = { ...options, groupBy: void 0 };
const component = mountWithIntl(
<MetricsExplorerChartContextMenu
timeRange={timeRange}
source={source}
series={series}
options={customOptions}
onFilter={onFilter}
uiCapabilities={customUICapabilities}
/>
);
expect(component.find('button').length).toBe(0);
});
});

describe('helpers', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
EuiContextMenuPanelDescriptor,
EuiPopover,
} from '@elastic/eui';
import { UICapabilities } from 'ui/capabilities';
import DateMath from '@elastic/datemath';
import { MetricsExplorerSeries } from '../../../server/routes/metrics_explorer/types';
import {
Expand All @@ -29,6 +30,7 @@ interface Props {
series: MetricsExplorerSeries;
source?: SourceConfiguration;
timeRange: MetricsExplorerTimeOptions;
uiCapabilities: UICapabilities;
}

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

export const MetricsExplorerChartContextMenu = injectI18n(
({ intl, onFilter, options, series, source, timeRange }: Props) => {
({ intl, onFilter, options, series, source, timeRange, uiCapabilities }: Props) => {
const [isPopoverOpen, setPopoverState] = useState(false);
const supportFiltering = options.groupBy != null && onFilter != null;
const handleFilter = useCallback(
Expand Down Expand Up @@ -114,12 +116,8 @@ export const MetricsExplorerChartContextMenu = injectI18n(
]
: [];

const panels: EuiContextMenuPanelDescriptor[] = [
{
id: 0,
title: 'Actions',
items: [
...filterByItem,
const openInVisualize = uiCapabilities.visualize.show
? [
{
name: intl.formatMessage({
id: 'xpack.infra.metricsExplorer.openInTSVB',
Expand All @@ -130,10 +128,22 @@ export const MetricsExplorerChartContextMenu = injectI18n(
disabled: options.metrics.length === 0,
'data-test-subj': 'metricsExplorerAction-OpenInTSVB',
},
...viewNodeDetail,
],
]
: [];

const itemPanels = [...filterByItem, ...openInVisualize, ...viewNodeDetail];

// If there are no itemPanels then there is no reason to show the actions button.
if (itemPanels.length === 0) return null;

const panels: EuiContextMenuPanelDescriptor[] = [
{
id: 0,
title: 'Actions',
items: itemPanels,
},
];

const handleClose = () => setPopoverState(false);
const handleOpen = () => setPopoverState(true);
const actionAriaLabel = intl.formatMessage(
Expand Down

0 comments on commit 2f029e6

Please sign in to comment.