diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/AggregationField.test.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/AggregationField.test.tsx
new file mode 100644
index 00000000000..c4fbc01027e
--- /dev/null
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/AggregationField.test.tsx
@@ -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();
+ 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();
+ expect(screen.queryByText('bar')).toBeInTheDocument();
+ expect(screen.queryByText('foo')).not.toBeInTheDocument();
+ });
+});
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/AggregationField.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/AggregationField.tsx
index 854b7fe03af..1407bdd60f2 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/AggregationField.tsx
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/AggregationField.tsx
@@ -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 = ({
[onQueryChange, query]
);
- const options = useMemo(
- () => [...aggregationOptions, variableOptionGroup],
- [aggregationOptions, variableOptionGroup]
- );
+ const options = addValueToOptions(aggregationOptions, variableOptionGroup, query.azureMonitor?.aggregation);
return (
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNameField.test.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNameField.test.tsx
new file mode 100644
index 00000000000..aff65cef929
--- /dev/null
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNameField.test.tsx
@@ -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();
+ 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();
+ expect(screen.queryByText('bar')).toBeInTheDocument();
+ expect(screen.queryByText('foo')).not.toBeInTheDocument();
+ });
+});
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNameField.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNameField.tsx
index 62106a63a81..4f73c551690 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNameField.tsx
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNameField.tsx
@@ -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 = ({ metricNames, query, variab
[onQueryChange, query]
);
- const options = useMemo(() => [...metricNames, variableOptionGroup], [metricNames, variableOptionGroup]);
+ const options = addValueToOptions(metricNames, variableOptionGroup, query.azureMonitor?.metricName);
return (
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx
index 124c20a6a3b..4f53d8a4c8e 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx
@@ -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 = ({
[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 (
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/TimeGrainField.test.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/TimeGrainField.test.tsx
new file mode 100644
index 00000000000..e1c0aa5bf00
--- /dev/null
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/TimeGrainField.test.tsx
@@ -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();
+ 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();
+ expect(screen.queryByText('1h')).toBeInTheDocument();
+ expect(screen.queryByText('15m')).not.toBeInTheDocument();
+ });
+});
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/TimeGrainField.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/TimeGrainField.tsx
index 7d70eff174a..d39de88c99c 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/TimeGrainField.tsx
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/TimeGrainField.tsx
@@ -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 = ({
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 (
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/types/types.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/types/types.ts
index 04879f9c8e4..e3757299436 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/types/types.ts
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/types/types.ts
@@ -158,12 +158,14 @@ export interface AzureMonitorOption {
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;
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/common.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/common.ts
index 4a89f1e2ab2..59e6f1d9b27 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/common.ts
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/common.ts
@@ -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(timeGrains: T[]) {
const allowedTimeGrainsMs: number[] = [];
timeGrains.forEach((tg: any) => {