add query header (#51072)

This commit is contained in:
Kevin Yu 2022-06-20 07:06:14 -07:00 committed by GitHub
parent 3273588cc0
commit d8d1ca8151
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 235 additions and 31 deletions

View File

@ -1,4 +1,4 @@
import { CloudMonitoringQuery, EditorMode, MetricQuery, QueryType } from '../types';
import { AlignmentTypes, CloudMonitoringQuery, EditorMode, MetricQuery, QueryType, SLOQuery } from '../types';
export const createMockMetricQuery: (overrides?: Partial<MetricQuery>) => MetricQuery = (
overrides?: Partial<MetricQuery>
@ -13,12 +13,29 @@ export const createMockMetricQuery: (overrides?: Partial<MetricQuery>) => Metric
};
};
export const createMockQuery: () => CloudMonitoringQuery = () => {
export const createMockSLOQuery: (overrides?: Partial<SLOQuery>) => SLOQuery = (overrides) => {
return {
projectName: 'projectName',
alignmentPeriod: 'cloud-monitoring-auto',
perSeriesAligner: AlignmentTypes.ALIGN_MEAN,
aliasBy: '',
selectorName: 'select_slo_health',
serviceId: '',
serviceName: '',
sloId: '',
sloName: '',
...overrides,
};
};
export const createMockQuery: (overrides?: Partial<CloudMonitoringQuery>) => CloudMonitoringQuery = (overrides) => {
return {
refId: 'cloudMonitoringRefId',
queryType: QueryType.METRICS,
intervalMs: 0,
type: 'timeSeriesQuery',
metricQuery: createMockMetricQuery(),
...overrides,
metricQuery: createMockMetricQuery(overrides?.metricQuery),
sloQuery: createMockSLOQuery(overrides?.sloQuery),
};
};

View File

@ -0,0 +1,107 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { openMenu, select } from 'react-select-event';
import { createMockQuery, createMockSLOQuery } from '../../__mocks__/cloudMonitoringQuery';
import { EditorMode, QueryType } from '../../types';
import { QueryHeader } from './QueryHeader';
describe('QueryHeader', () => {
it('renders an editor mode radio group if query type is a metric query', () => {
const query = createMockQuery();
const { metricQuery } = query;
const sloQuery = createMockSLOQuery();
const onChange = jest.fn();
const onRunQuery = jest.fn();
render(
<QueryHeader
query={query}
metricQuery={metricQuery}
sloQuery={sloQuery}
onChange={onChange}
onRunQuery={onRunQuery}
/>
);
expect(screen.getByLabelText(/Query type/)).toBeInTheDocument();
expect(screen.getByLabelText('Builder')).toBeInTheDocument();
expect(screen.getByLabelText('MQL')).toBeInTheDocument();
});
it('does not render an editor mode radio group if query type is a SLO query', () => {
const query = createMockQuery({ queryType: QueryType.SLO });
const { metricQuery } = query;
const sloQuery = createMockSLOQuery();
const onChange = jest.fn();
const onRunQuery = jest.fn();
render(
<QueryHeader
query={query}
metricQuery={metricQuery}
sloQuery={sloQuery}
onChange={onChange}
onRunQuery={onRunQuery}
/>
);
expect(screen.getByLabelText(/Query type/)).toBeInTheDocument();
expect(screen.queryByLabelText('Builder')).not.toBeInTheDocument();
expect(screen.queryByLabelText('MQL')).not.toBeInTheDocument();
});
it('can change query types', async () => {
const query = createMockQuery();
const { metricQuery } = query;
const sloQuery = createMockSLOQuery();
const onChange = jest.fn();
const onRunQuery = jest.fn();
render(
<QueryHeader
query={query}
metricQuery={metricQuery}
sloQuery={sloQuery}
onChange={onChange}
onRunQuery={onRunQuery}
/>
);
const queryType = screen.getByLabelText(/Query type/);
await openMenu(queryType);
await select(screen.getByLabelText('Select options menu'), 'Service Level Objectives (SLO)');
expect(onChange).toBeCalledWith(expect.objectContaining({ queryType: QueryType.SLO }));
});
it('can change editor modes when query is a metric query type', async () => {
const query = createMockQuery();
const { metricQuery } = query;
const sloQuery = createMockSLOQuery();
const onChange = jest.fn();
const onRunQuery = jest.fn();
render(
<QueryHeader
query={query}
metricQuery={metricQuery}
sloQuery={sloQuery}
onChange={onChange}
onRunQuery={onRunQuery}
/>
);
const builder = screen.getByLabelText('Builder');
const MQL = screen.getByLabelText('MQL');
expect(builder).toBeChecked();
expect(MQL).not.toBeChecked();
await userEvent.click(MQL);
expect(onChange).toBeCalledWith(
expect.objectContaining({ metricQuery: expect.objectContaining({ editorMode: EditorMode.MQL }) })
);
});
});

View File

@ -0,0 +1,57 @@
import React from 'react';
import { EditorHeader, FlexItem, InlineSelect } from '@grafana/experimental';
import { RadioButtonGroup } from '@grafana/ui';
import { QUERY_TYPES } from '../../constants';
import { EditorMode, CloudMonitoringQuery, QueryType, SLOQuery, MetricQuery } from '../../types';
export interface QueryEditorHeaderProps {
query: CloudMonitoringQuery;
metricQuery: MetricQuery;
sloQuery: SLOQuery;
onChange: (value: CloudMonitoringQuery) => void;
onRunQuery: () => void;
}
const EDITOR_MODES = [
{ label: 'Builder', value: EditorMode.Visual },
{ label: 'MQL', value: EditorMode.MQL },
];
export const QueryHeader = (props: QueryEditorHeaderProps) => {
const { query, metricQuery, sloQuery, onChange, onRunQuery } = props;
const { queryType } = query;
const { editorMode } = metricQuery;
return (
<EditorHeader>
<InlineSelect
label="Query type"
options={QUERY_TYPES}
value={queryType}
onChange={({ value }) => {
onChange({ ...query, sloQuery, queryType: value! });
onRunQuery();
}}
/>
<FlexItem grow={1} />
{queryType !== QueryType.SLO && (
<RadioButtonGroup
size="sm"
options={EDITOR_MODES}
value={editorMode || EditorMode.Visual}
onChange={(value) => {
onChange({
...query,
metricQuery: {
...metricQuery,
editorMode: value,
},
});
}}
/>
)}
</EditorHeader>
);
};

View File

@ -11,6 +11,7 @@ import CloudMonitoringDatasource from '../datasource';
import { CloudMonitoringQuery, EditorMode, MetricQuery, QueryType, SLOQuery, CloudMonitoringOptions } from '../types';
import { MetricQueryEditor as ExperimentalMetricQueryEditor } from './Experimental/MetricQueryEditor';
import { QueryHeader } from './Experimental/QueryHeader';
import { defaultQuery } from './MetricQueryEditor';
import { defaultQuery as defaultSLOQuery } from './SLO/SLOQueryEditor';
@ -57,7 +58,42 @@ export class QueryEditor extends PureComponent<Props> {
options: datasource.getVariables().map(toOption),
};
return (
return config.featureToggles.cloudMonitoringExperimentalUI ? (
<EditorRows>
<QueryHeader
query={query}
metricQuery={metricQuery}
sloQuery={sloQuery}
onChange={onChange}
onRunQuery={onRunQuery}
/>
{queryType === QueryType.METRICS && (
<ExperimentalMetricQueryEditor
refId={query.refId}
variableOptionGroup={variableOptionGroup}
customMetaData={customMetaData}
onChange={(metricQuery: MetricQuery) => {
this.props.onChange({ ...this.props.query, metricQuery });
}}
onRunQuery={onRunQuery}
datasource={datasource}
query={metricQuery}
/>
)}
{queryType === QueryType.SLO && (
<SLOQueryEditor
refId={query.refId}
variableOptionGroup={variableOptionGroup}
customMetaData={customMetaData}
onChange={(query: SLOQuery) => this.onQueryChange('sloQuery', query)}
onRunQuery={onRunQuery}
datasource={datasource}
query={sloQuery}
/>
)}
</EditorRows>
) : (
<EditorRows>
<QueryEditorRow
label="Query type"
@ -94,32 +130,19 @@ export class QueryEditor extends PureComponent<Props> {
/>
</QueryEditorRow>
{queryType === QueryType.METRICS &&
(config.featureToggles.cloudMonitoringExperimentalUI ? (
<ExperimentalMetricQueryEditor
refId={query.refId}
variableOptionGroup={variableOptionGroup}
customMetaData={customMetaData}
onChange={(metricQuery: MetricQuery) => {
this.props.onChange({ ...this.props.query, metricQuery });
}}
onRunQuery={onRunQuery}
datasource={datasource}
query={metricQuery}
/>
) : (
<MetricQueryEditor
refId={query.refId}
variableOptionGroup={variableOptionGroup}
customMetaData={customMetaData}
onChange={(metricQuery: MetricQuery) => {
this.props.onChange({ ...this.props.query, metricQuery });
}}
onRunQuery={onRunQuery}
datasource={datasource}
query={metricQuery}
/>
))}
{queryType === QueryType.METRICS && (
<MetricQueryEditor
refId={query.refId}
variableOptionGroup={variableOptionGroup}
customMetaData={customMetaData}
onChange={(metricQuery: MetricQuery) => {
this.props.onChange({ ...this.props.query, metricQuery });
}}
onRunQuery={onRunQuery}
datasource={datasource}
query={metricQuery}
/>
)}
{queryType === QueryType.SLO && (
<SLOQueryEditor
@ -130,7 +153,7 @@ export class QueryEditor extends PureComponent<Props> {
onRunQuery={onRunQuery}
datasource={datasource}
query={sloQuery}
></SLOQueryEditor>
/>
)}
</EditorRows>
);