mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
AzureMonitor: Update ARG Subscription selection (#66890)
* Update ARG Subscription selection - Filter out queries that do not contain at least one subscription - Refactor SubscriptionField component - Display error if no subscriptions are selected - Update tests * Fix test
This commit is contained in:
parent
3c0e896282
commit
f3dbb7b34a
@ -12,7 +12,7 @@ export default class AzureResourceGraphDatasource extends DataSourceWithBackend<
|
||||
AzureDataSourceJsonData
|
||||
> {
|
||||
filterQuery(item: AzureMonitorQuery): boolean {
|
||||
return !!item.azureResourceGraph?.query;
|
||||
return !!item.azureResourceGraph?.query && !!item.subscriptions && item.subscriptions.length > 0;
|
||||
}
|
||||
|
||||
applyTemplateVariables(target: AzureMonitorQuery, scopedVars: ScopedVars): AzureMonitorQuery {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
|
||||
import createMockDatasource from '../../__mocks__/datasource';
|
||||
@ -118,4 +119,67 @@ describe('ArgQueryEditor', () => {
|
||||
).toHaveTextContent('$test');
|
||||
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ subscriptions: ['$test'] }));
|
||||
});
|
||||
|
||||
it('should display an error if no subscription is selected', async () => {
|
||||
const onChange = jest.fn();
|
||||
const datasource = createMockDatasource({
|
||||
getSubscriptions: jest.fn().mockResolvedValue([]),
|
||||
});
|
||||
const query = createMockQuery({
|
||||
subscriptions: [],
|
||||
});
|
||||
render(
|
||||
<ArgQueryEditor
|
||||
{...defaultProps}
|
||||
datasource={datasource}
|
||||
onChange={onChange}
|
||||
query={query}
|
||||
variableOptionGroup={{ label: 'Template Variables', options: [] }}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(await waitFor(() => screen.getByText('At least one subscription must be chosen.'))).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display an error if subscriptions are cleared', async () => {
|
||||
const onChange = jest.fn();
|
||||
const datasource = createMockDatasource({
|
||||
getSubscriptions: jest.fn().mockResolvedValue([{ text: 'foo', value: 'test-subscription-value' }]),
|
||||
});
|
||||
const query = createMockQuery({
|
||||
subscription: undefined,
|
||||
subscriptions: ['test-subscription-value'],
|
||||
});
|
||||
const { rerender } = render(
|
||||
<ArgQueryEditor
|
||||
{...defaultProps}
|
||||
query={query}
|
||||
datasource={datasource}
|
||||
onChange={onChange}
|
||||
variableOptionGroup={{ label: 'Template Variables', options: [] }}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(datasource.getSubscriptions).toHaveBeenCalled();
|
||||
expect(await waitFor(() => onChange)).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ subscriptions: ['test-subscription-value'] })
|
||||
);
|
||||
expect(await waitFor(() => screen.findByText('foo'))).toBeInTheDocument();
|
||||
|
||||
const clear = screen.getByLabelText('select-clear-value');
|
||||
await userEvent.click(clear);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ subscriptions: [] }));
|
||||
|
||||
rerender(
|
||||
<ArgQueryEditor
|
||||
{...defaultProps}
|
||||
datasource={datasource}
|
||||
onChange={onChange}
|
||||
query={{ ...query, subscriptions: [] }}
|
||||
variableOptionGroup={{ label: 'Template Variables', options: [] }}
|
||||
/>
|
||||
);
|
||||
expect(await waitFor(() => screen.getByText('At least one subscription must be chosen.'))).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -6,9 +6,9 @@ import { EditorFieldGroup, EditorRow, EditorRows } from '@grafana/experimental';
|
||||
import Datasource from '../../datasource';
|
||||
import { selectors } from '../../e2e/selectors';
|
||||
import { AzureMonitorErrorish, AzureMonitorOption, AzureMonitorQuery } from '../../types';
|
||||
import SubscriptionField from '../SubscriptionField';
|
||||
|
||||
import QueryField from './QueryField';
|
||||
import SubscriptionField from './SubscriptionField';
|
||||
|
||||
interface ArgQueryEditorProps {
|
||||
query: AzureMonitorQuery;
|
||||
@ -81,7 +81,6 @@ const ArgQueryEditor = ({
|
||||
<EditorRow>
|
||||
<EditorFieldGroup>
|
||||
<SubscriptionField
|
||||
multiSelect
|
||||
subscriptions={subscriptions}
|
||||
query={query}
|
||||
datasource={datasource}
|
||||
|
@ -0,0 +1,66 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { FieldValidationMessage, MultiSelect } from '@grafana/ui';
|
||||
|
||||
import { selectors } from '../../e2e/selectors';
|
||||
import { AzureMonitorQuery, AzureQueryEditorFieldProps, AzureMonitorOption } from '../../types';
|
||||
import { findOptions } from '../../utils/common';
|
||||
import { Field } from '../Field';
|
||||
|
||||
interface SubscriptionFieldProps extends AzureQueryEditorFieldProps {
|
||||
onQueryChange: (newQuery: AzureMonitorQuery) => void;
|
||||
subscriptions: AzureMonitorOption[];
|
||||
}
|
||||
|
||||
const SubscriptionField = ({ query, subscriptions, variableOptionGroup, onQueryChange }: SubscriptionFieldProps) => {
|
||||
const [error, setError] = useState<boolean>(false);
|
||||
const [values, setValues] = useState<Array<SelectableValue<string>>>([]);
|
||||
const options = useMemo(() => [...subscriptions, variableOptionGroup], [subscriptions, variableOptionGroup]);
|
||||
|
||||
useEffect(() => {
|
||||
if (query.subscriptions && query.subscriptions.length > 0) {
|
||||
setValues(findOptions([...subscriptions, ...variableOptionGroup.options], query.subscriptions));
|
||||
setError(false);
|
||||
} else {
|
||||
setError(true);
|
||||
}
|
||||
}, [query.subscriptions, subscriptions, variableOptionGroup.options]);
|
||||
|
||||
const onChange = (change: Array<SelectableValue<string>>) => {
|
||||
if (!change || change.length === 0) {
|
||||
setValues([]);
|
||||
onQueryChange({
|
||||
...query,
|
||||
subscriptions: [],
|
||||
});
|
||||
setError(true);
|
||||
} else {
|
||||
const newSubs = change.map((c) => c.value ?? '');
|
||||
onQueryChange({
|
||||
...query,
|
||||
subscriptions: newSubs,
|
||||
});
|
||||
setValues(findOptions([...subscriptions, ...variableOptionGroup.options], newSubs));
|
||||
setError(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Field label="Subscriptions" data-testid={selectors.components.queryEditor.argsQueryEditor.subscriptions.input}>
|
||||
<>
|
||||
<MultiSelect
|
||||
isClearable
|
||||
value={values}
|
||||
inputId="azure-monitor-subscriptions-field"
|
||||
onChange={onChange}
|
||||
options={options}
|
||||
width={38}
|
||||
/>
|
||||
{error ? <FieldValidationMessage>At least one subscription must be chosen.</FieldValidationMessage> : null}
|
||||
</>
|
||||
</Field>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubscriptionField;
|
@ -1,94 +0,0 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { Select, MultiSelect } from '@grafana/ui';
|
||||
|
||||
import { selectors } from '../e2e/selectors';
|
||||
import { AzureMonitorQuery, AzureQueryEditorFieldProps, AzureMonitorOption, AzureQueryType } from '../types';
|
||||
import { findOptions } from '../utils/common';
|
||||
|
||||
import { Field } from './Field';
|
||||
|
||||
interface SubscriptionFieldProps extends AzureQueryEditorFieldProps {
|
||||
onQueryChange: (newQuery: AzureMonitorQuery) => void;
|
||||
subscriptions: AzureMonitorOption[];
|
||||
multiSelect?: boolean;
|
||||
}
|
||||
|
||||
const SubscriptionField = ({
|
||||
query,
|
||||
subscriptions,
|
||||
variableOptionGroup,
|
||||
onQueryChange,
|
||||
multiSelect = false,
|
||||
}: SubscriptionFieldProps) => {
|
||||
const handleChange = useCallback(
|
||||
(change: SelectableValue<string>) => {
|
||||
if (!change.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newQuery: AzureMonitorQuery = {
|
||||
...query,
|
||||
subscription: change.value,
|
||||
};
|
||||
|
||||
if (query.queryType === AzureQueryType.AzureMonitor) {
|
||||
newQuery.azureMonitor = {
|
||||
...newQuery.azureMonitor,
|
||||
resources: undefined,
|
||||
metricNamespace: undefined,
|
||||
metricName: undefined,
|
||||
aggregation: undefined,
|
||||
timeGrain: '',
|
||||
dimensionFilters: [],
|
||||
};
|
||||
}
|
||||
|
||||
onQueryChange(newQuery);
|
||||
},
|
||||
[query, onQueryChange]
|
||||
);
|
||||
|
||||
const onSubscriptionsChange = useCallback(
|
||||
(change: Array<SelectableValue<string>>) => {
|
||||
if (!change) {
|
||||
return;
|
||||
}
|
||||
|
||||
onQueryChange({
|
||||
...query,
|
||||
subscriptions: change.map((c) => c.value ?? ''),
|
||||
});
|
||||
},
|
||||
[query, onQueryChange]
|
||||
);
|
||||
|
||||
const options = useMemo(() => [...subscriptions, variableOptionGroup], [subscriptions, variableOptionGroup]);
|
||||
|
||||
return multiSelect ? (
|
||||
<Field label="Subscriptions" data-testid={selectors.components.queryEditor.argsQueryEditor.subscriptions.input}>
|
||||
<MultiSelect
|
||||
isClearable
|
||||
value={findOptions([...subscriptions, ...variableOptionGroup.options], query.subscriptions)}
|
||||
inputId="azure-monitor-subscriptions-field"
|
||||
onChange={onSubscriptionsChange}
|
||||
options={options}
|
||||
width={38}
|
||||
/>
|
||||
</Field>
|
||||
) : (
|
||||
<Field label="Subscription" data-testid={selectors.components.queryEditor.argsQueryEditor.subscriptions.input}>
|
||||
<Select
|
||||
value={query.subscription}
|
||||
inputId="azure-monitor-subscriptions-field"
|
||||
onChange={handleChange}
|
||||
options={options}
|
||||
width={38}
|
||||
allowCustomValue
|
||||
/>
|
||||
</Field>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubscriptionField;
|
@ -100,7 +100,7 @@ describe('VariableEditor:', () => {
|
||||
it('should render', async () => {
|
||||
render(<VariableEditor {...ARGqueryProps} />);
|
||||
await waitFor(() => screen.queryByTestId('mockeditor'));
|
||||
expect(screen.queryByLabelText('Subscriptions')).toBeInTheDocument();
|
||||
await waitFor(() => screen.queryByLabelText('Subscriptions'));
|
||||
expect(screen.queryByText('Resource Graph')).toBeInTheDocument();
|
||||
expect(screen.queryByLabelText('Select subscription')).not.toBeInTheDocument();
|
||||
expect(screen.queryByLabelText('Select query type')).not.toBeInTheDocument();
|
||||
|
Loading…
Reference in New Issue
Block a user