mirror of
https://github.com/grafana/grafana.git
synced 2025-09-26 02:14:06 +08:00
add query header (#51072)
This commit is contained in:
@ -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 = (
|
export const createMockMetricQuery: (overrides?: Partial<MetricQuery>) => MetricQuery = (
|
||||||
overrides?: Partial<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 {
|
return {
|
||||||
refId: 'cloudMonitoringRefId',
|
refId: 'cloudMonitoringRefId',
|
||||||
queryType: QueryType.METRICS,
|
queryType: QueryType.METRICS,
|
||||||
intervalMs: 0,
|
intervalMs: 0,
|
||||||
type: 'timeSeriesQuery',
|
type: 'timeSeriesQuery',
|
||||||
metricQuery: createMockMetricQuery(),
|
...overrides,
|
||||||
|
metricQuery: createMockMetricQuery(overrides?.metricQuery),
|
||||||
|
sloQuery: createMockSLOQuery(overrides?.sloQuery),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -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 }) })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -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>
|
||||||
|
);
|
||||||
|
};
|
@ -11,6 +11,7 @@ import CloudMonitoringDatasource from '../datasource';
|
|||||||
import { CloudMonitoringQuery, EditorMode, MetricQuery, QueryType, SLOQuery, CloudMonitoringOptions } from '../types';
|
import { CloudMonitoringQuery, EditorMode, MetricQuery, QueryType, SLOQuery, CloudMonitoringOptions } from '../types';
|
||||||
|
|
||||||
import { MetricQueryEditor as ExperimentalMetricQueryEditor } from './Experimental/MetricQueryEditor';
|
import { MetricQueryEditor as ExperimentalMetricQueryEditor } from './Experimental/MetricQueryEditor';
|
||||||
|
import { QueryHeader } from './Experimental/QueryHeader';
|
||||||
import { defaultQuery } from './MetricQueryEditor';
|
import { defaultQuery } from './MetricQueryEditor';
|
||||||
import { defaultQuery as defaultSLOQuery } from './SLO/SLOQueryEditor';
|
import { defaultQuery as defaultSLOQuery } from './SLO/SLOQueryEditor';
|
||||||
|
|
||||||
@ -57,7 +58,42 @@ export class QueryEditor extends PureComponent<Props> {
|
|||||||
options: datasource.getVariables().map(toOption),
|
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>
|
<EditorRows>
|
||||||
<QueryEditorRow
|
<QueryEditorRow
|
||||||
label="Query type"
|
label="Query type"
|
||||||
@ -94,32 +130,19 @@ export class QueryEditor extends PureComponent<Props> {
|
|||||||
/>
|
/>
|
||||||
</QueryEditorRow>
|
</QueryEditorRow>
|
||||||
|
|
||||||
{queryType === QueryType.METRICS &&
|
{queryType === QueryType.METRICS && (
|
||||||
(config.featureToggles.cloudMonitoringExperimentalUI ? (
|
<MetricQueryEditor
|
||||||
<ExperimentalMetricQueryEditor
|
refId={query.refId}
|
||||||
refId={query.refId}
|
variableOptionGroup={variableOptionGroup}
|
||||||
variableOptionGroup={variableOptionGroup}
|
customMetaData={customMetaData}
|
||||||
customMetaData={customMetaData}
|
onChange={(metricQuery: MetricQuery) => {
|
||||||
onChange={(metricQuery: MetricQuery) => {
|
this.props.onChange({ ...this.props.query, metricQuery });
|
||||||
this.props.onChange({ ...this.props.query, metricQuery });
|
}}
|
||||||
}}
|
onRunQuery={onRunQuery}
|
||||||
onRunQuery={onRunQuery}
|
datasource={datasource}
|
||||||
datasource={datasource}
|
query={metricQuery}
|
||||||
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.SLO && (
|
{queryType === QueryType.SLO && (
|
||||||
<SLOQueryEditor
|
<SLOQueryEditor
|
||||||
@ -130,7 +153,7 @@ export class QueryEditor extends PureComponent<Props> {
|
|||||||
onRunQuery={onRunQuery}
|
onRunQuery={onRunQuery}
|
||||||
datasource={datasource}
|
datasource={datasource}
|
||||||
query={sloQuery}
|
query={sloQuery}
|
||||||
></SLOQueryEditor>
|
/>
|
||||||
)}
|
)}
|
||||||
</EditorRows>
|
</EditorRows>
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user