mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Azure Monitor: Add current value to editor options (#60726)
This commit is contained in:
parent
bb5ac924ae
commit
7a679db08b
@ -0,0 +1,45 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import createMockDatasource from '../../__mocks__/datasource';
|
||||
import createMockQuery from '../../__mocks__/query';
|
||||
import { AzureMonitorOption } from '../../types';
|
||||
|
||||
import AggregationField from './AggregationField';
|
||||
|
||||
const props = {
|
||||
aggregationOptions: [],
|
||||
query: createMockQuery(),
|
||||
datasource: createMockDatasource(),
|
||||
variableOptionGroup: { label: 'Templates', options: [] },
|
||||
onQueryChange: jest.fn(),
|
||||
setError: jest.fn(),
|
||||
isLoading: false,
|
||||
};
|
||||
|
||||
describe('AggregationField', () => {
|
||||
it('should render the current value', async () => {
|
||||
const aggregationOptions: AzureMonitorOption[] = [{ label: 'foo', value: 'foo' }];
|
||||
const query = {
|
||||
...props.query,
|
||||
azureMonitor: {
|
||||
aggregation: 'foo',
|
||||
},
|
||||
};
|
||||
render(<AggregationField {...props} aggregationOptions={aggregationOptions} query={query} />);
|
||||
expect(screen.queryByText('foo')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render the current value even if it is not in the list of options', async () => {
|
||||
const aggregationOptions: AzureMonitorOption[] = [{ label: 'foo', value: 'foo' }];
|
||||
const query = {
|
||||
...props.query,
|
||||
azureMonitor: {
|
||||
aggregation: 'bar',
|
||||
},
|
||||
};
|
||||
render(<AggregationField {...props} aggregationOptions={aggregationOptions} query={query} />);
|
||||
expect(screen.queryByText('bar')).toBeInTheDocument();
|
||||
expect(screen.queryByText('foo')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -1,9 +1,10 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { Select } from '@grafana/ui';
|
||||
|
||||
import { AzureQueryEditorFieldProps, AzureMonitorOption } from '../../types';
|
||||
import { addValueToOptions } from '../../utils/common';
|
||||
import { Field } from '../Field';
|
||||
|
||||
import { setAggregation } from './setQueryValue';
|
||||
@ -32,10 +33,7 @@ const AggregationField: React.FC<AggregationFieldProps> = ({
|
||||
[onQueryChange, query]
|
||||
);
|
||||
|
||||
const options = useMemo(
|
||||
() => [...aggregationOptions, variableOptionGroup],
|
||||
[aggregationOptions, variableOptionGroup]
|
||||
);
|
||||
const options = addValueToOptions(aggregationOptions, variableOptionGroup, query.azureMonitor?.aggregation);
|
||||
|
||||
return (
|
||||
<Field label="Aggregation">
|
||||
|
@ -0,0 +1,44 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import createMockDatasource from '../../__mocks__/datasource';
|
||||
import createMockQuery from '../../__mocks__/query';
|
||||
import { AzureMonitorOption } from '../../types';
|
||||
|
||||
import MetricNameField from './MetricNameField';
|
||||
|
||||
const props = {
|
||||
metricNames: [],
|
||||
query: createMockQuery(),
|
||||
datasource: createMockDatasource(),
|
||||
variableOptionGroup: { label: 'Templates', options: [] },
|
||||
onQueryChange: jest.fn(),
|
||||
setError: jest.fn(),
|
||||
};
|
||||
|
||||
describe('MetricNameField', () => {
|
||||
it('should render the current value', async () => {
|
||||
const metricNames: AzureMonitorOption[] = [{ label: 'foo', value: 'foo' }];
|
||||
const query = {
|
||||
...props.query,
|
||||
azureMonitor: {
|
||||
metricName: 'foo',
|
||||
},
|
||||
};
|
||||
render(<MetricNameField {...props} metricNames={metricNames} query={query} />);
|
||||
expect(screen.queryByText('foo')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render the current value even if it is not in the list of options', async () => {
|
||||
const metricNames: AzureMonitorOption[] = [{ label: 'foo', value: 'foo' }];
|
||||
const query = {
|
||||
...props.query,
|
||||
azureMonitor: {
|
||||
metricName: 'bar',
|
||||
},
|
||||
};
|
||||
render(<MetricNameField {...props} metricNames={metricNames} query={query} />);
|
||||
expect(screen.queryByText('bar')).toBeInTheDocument();
|
||||
expect(screen.queryByText('foo')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -1,10 +1,11 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { Select } from '@grafana/ui';
|
||||
|
||||
import { selectors } from '../../e2e/selectors';
|
||||
import { AzureQueryEditorFieldProps, AzureMonitorOption } from '../../types';
|
||||
import { addValueToOptions } from '../../utils/common';
|
||||
import { Field } from '../Field';
|
||||
|
||||
import { setMetricName } from './setQueryValue';
|
||||
@ -26,7 +27,7 @@ const MetricNameField: React.FC<MetricNameProps> = ({ metricNames, query, variab
|
||||
[onQueryChange, query]
|
||||
);
|
||||
|
||||
const options = useMemo(() => [...metricNames, variableOptionGroup], [metricNames, variableOptionGroup]);
|
||||
const options = addValueToOptions(metricNames, variableOptionGroup, query.azureMonitor?.metricName);
|
||||
|
||||
return (
|
||||
<Field label="Metric" data-testid={selectors.components.queryEditor.metricsQueryEditor.metricName.input}>
|
||||
|
@ -1,9 +1,10 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { Select } from '@grafana/ui';
|
||||
|
||||
import { AzureQueryEditorFieldProps, AzureMonitorOption } from '../../types';
|
||||
import { addValueToOptions } from '../../utils/common';
|
||||
import { Field } from '../Field';
|
||||
|
||||
import { setCustomNamespace } from './setQueryValue';
|
||||
@ -30,14 +31,8 @@ const MetricNamespaceField: React.FC<MetricNamespaceFieldProps> = ({
|
||||
[onQueryChange, query]
|
||||
);
|
||||
|
||||
const options = useMemo(() => [...metricNamespaces, variableOptionGroup], [metricNamespaces, variableOptionGroup]);
|
||||
const optionValues = metricNamespaces
|
||||
.map((m) => m.value.toLowerCase())
|
||||
.concat(variableOptionGroup.options.map((p) => p.value));
|
||||
const value = query.azureMonitor?.customNamespace || query.azureMonitor?.metricNamespace;
|
||||
if (value && !optionValues.includes(value.toLowerCase())) {
|
||||
options.push({ label: value, value });
|
||||
}
|
||||
const options = addValueToOptions(metricNamespaces, variableOptionGroup, value);
|
||||
|
||||
return (
|
||||
<Field label="Metric namespace">
|
||||
|
@ -0,0 +1,45 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import createMockDatasource from '../../__mocks__/datasource';
|
||||
import createMockQuery from '../../__mocks__/query';
|
||||
import { AzureMonitorOption } from '../../types';
|
||||
|
||||
import TimeGrainField from './TimeGrainField';
|
||||
|
||||
const props = {
|
||||
timeGrainOptions: [],
|
||||
query: createMockQuery(),
|
||||
datasource: createMockDatasource(),
|
||||
variableOptionGroup: { label: 'Templates', options: [] },
|
||||
onQueryChange: jest.fn(),
|
||||
setError: jest.fn(),
|
||||
isLoading: false,
|
||||
};
|
||||
|
||||
describe('TimeGrainField', () => {
|
||||
it('should render the current value', async () => {
|
||||
const timeGrainOptions: AzureMonitorOption[] = [{ label: '15m', value: '15m' }];
|
||||
const query = {
|
||||
...props.query,
|
||||
azureMonitor: {
|
||||
timeGrain: '15m',
|
||||
},
|
||||
};
|
||||
render(<TimeGrainField {...props} timeGrainOptions={timeGrainOptions} query={query} />);
|
||||
expect(screen.queryByText('15m')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render the current value even if it is not in the list of options', async () => {
|
||||
const timeGrainOptions: AzureMonitorOption[] = [{ label: '15m', value: '15m' }];
|
||||
const query = {
|
||||
...props.query,
|
||||
azureMonitor: {
|
||||
timeGrain: '1h',
|
||||
},
|
||||
};
|
||||
render(<TimeGrainField {...props} timeGrainOptions={timeGrainOptions} query={query} />);
|
||||
expect(screen.queryByText('1h')).toBeInTheDocument();
|
||||
expect(screen.queryByText('15m')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -5,6 +5,7 @@ import { Select } from '@grafana/ui';
|
||||
|
||||
import TimegrainConverter from '../../time_grain_converter';
|
||||
import { AzureQueryEditorFieldProps, AzureMonitorOption } from '../../types';
|
||||
import { addValueToOptions } from '../../utils/common';
|
||||
import { Field } from '../Field';
|
||||
|
||||
import { setTimeGrain } from './setQueryValue';
|
||||
@ -48,8 +49,10 @@ const TimeGrainField: React.FC<TimeGrainFieldProps> = ({
|
||||
|
||||
const baseTimeGrains = timeGrainOptions.map((v) => (v.value === 'auto' ? { ...v, description: autoInterval } : v));
|
||||
|
||||
return [...baseTimeGrains, variableOptionGroup];
|
||||
}, [timeGrainOptions, variableOptionGroup]);
|
||||
const options = addValueToOptions(baseTimeGrains, variableOptionGroup, query.azureMonitor?.timeGrain);
|
||||
|
||||
return options;
|
||||
}, [timeGrainOptions, variableOptionGroup, query.azureMonitor?.timeGrain]);
|
||||
|
||||
return (
|
||||
<Field label="Time grain">
|
||||
|
@ -158,12 +158,14 @@ export interface AzureMonitorOption<T = string> {
|
||||
options?: AzureMonitorOption[];
|
||||
}
|
||||
|
||||
export type VariableOptionGroup = { label: string; options: AzureMonitorOption[] };
|
||||
|
||||
export interface AzureQueryEditorFieldProps {
|
||||
data?: PanelData;
|
||||
query: AzureMonitorQuery;
|
||||
datasource: Datasource;
|
||||
subscriptionId?: string;
|
||||
variableOptionGroup: { label: string; options: AzureMonitorOption[] };
|
||||
variableOptionGroup: VariableOptionGroup;
|
||||
|
||||
onQueryChange: (newQuery: AzureMonitorQuery) => void;
|
||||
setError: (source: string, error: AzureMonitorErrorish | undefined) => void;
|
||||
|
@ -4,7 +4,7 @@ import { rangeUtil } from '@grafana/data';
|
||||
import { VariableWithMultiSupport } from 'app/features/variables/types';
|
||||
|
||||
import TimegrainConverter from '../time_grain_converter';
|
||||
import { AzureMonitorOption } from '../types';
|
||||
import { AzureMonitorOption, VariableOptionGroup } from '../types';
|
||||
|
||||
export const hasOption = (options: AzureMonitorOption[], value: string): boolean =>
|
||||
options.some((v) => (v.options ? hasOption(v.options, value) : v.value === value));
|
||||
@ -22,6 +22,21 @@ export const findOptions = (options: AzureMonitorOption[], values: string[] = []
|
||||
|
||||
export const toOption = (v: { text: string; value: string }) => ({ value: v.value, label: v.text });
|
||||
|
||||
export const addValueToOptions = (
|
||||
values: AzureMonitorOption[],
|
||||
variableOptionGroup: VariableOptionGroup,
|
||||
value?: string
|
||||
) => {
|
||||
const options = [...values, variableOptionGroup];
|
||||
|
||||
const optionValues = values.map((m) => m.value.toLowerCase()).concat(variableOptionGroup.options.map((p) => p.value));
|
||||
if (value && !optionValues.includes(value.toLowerCase())) {
|
||||
options.push({ label: value, value });
|
||||
}
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
export function convertTimeGrainsToMs<T extends { value: string }>(timeGrains: T[]) {
|
||||
const allowedTimeGrainsMs: number[] = [];
|
||||
timeGrains.forEach((tg: any) => {
|
||||
|
Loading…
Reference in New Issue
Block a user