mirror of
https://github.com/grafana/grafana.git
synced 2024-11-24 09:50:29 -06:00
Remove PromExploreQueryEditor and PromQueryEditor (#60020)
Remove Prom editor
This commit is contained in:
parent
cf342f1933
commit
07d6b632b5
@ -6306,22 +6306,12 @@ exports[`better eslint`] = {
|
|||||||
"public/app/plugins/datasource/prometheus/components/PromExploreExtraField.test.tsx:5381": [
|
"public/app/plugins/datasource/prometheus/components/PromExploreExtraField.test.tsx:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||||
],
|
],
|
||||||
"public/app/plugins/datasource/prometheus/components/PromExploreQueryEditor.test.tsx:5381": [
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
|
||||||
],
|
|
||||||
"public/app/plugins/datasource/prometheus/components/PromLink.test.tsx:5381": [
|
"public/app/plugins/datasource/prometheus/components/PromLink.test.tsx:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||||
],
|
],
|
||||||
"public/app/plugins/datasource/prometheus/components/PromLink.tsx:5381": [
|
"public/app/plugins/datasource/prometheus/components/PromLink.tsx:5381": [
|
||||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||||
],
|
],
|
||||||
"public/app/plugins/datasource/prometheus/components/PromQueryEditor.test.tsx:5381": [
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
|
||||||
],
|
|
||||||
"public/app/plugins/datasource/prometheus/components/PromQueryEditor.tsx:5381": [
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
|
||||||
],
|
|
||||||
"public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx:5381": [
|
"public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||||
],
|
],
|
||||||
|
@ -1,144 +0,0 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { LoadingState, PanelData, toUtc, TimeRange } from '@grafana/data';
|
|
||||||
|
|
||||||
import { PrometheusDatasource } from '../datasource';
|
|
||||||
import { PromQuery } from '../types';
|
|
||||||
|
|
||||||
import { testIds as extraFieldTestIds } from './PromExploreExtraField';
|
|
||||||
import { PromExploreQueryEditor, testIds } from './PromExploreQueryEditor';
|
|
||||||
|
|
||||||
// the monaco-based editor uses lazy-loading and that does not work
|
|
||||||
// well with this test, and we do not need the monaco-related
|
|
||||||
// functionality in this test anyway, so we mock it out.
|
|
||||||
jest.mock('./monaco-query-field/MonacoQueryFieldWrapper', () => {
|
|
||||||
const fakeQueryField = () => <div>prometheus query field</div>;
|
|
||||||
return {
|
|
||||||
MonacoQueryFieldWrapper: fakeQueryField,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const setup = (propOverrides?: object) => {
|
|
||||||
const datasourceMock: unknown = {
|
|
||||||
languageProvider: {
|
|
||||||
syntax: () => {},
|
|
||||||
getLabelKeys: () => [],
|
|
||||||
metrics: [],
|
|
||||||
start: () => Promise.resolve([]),
|
|
||||||
},
|
|
||||||
getInitHints: () => [],
|
|
||||||
exemplarsAvailable: true,
|
|
||||||
};
|
|
||||||
const datasource: PrometheusDatasource = datasourceMock as PrometheusDatasource;
|
|
||||||
const onRunQuery = jest.fn();
|
|
||||||
const onChange = jest.fn();
|
|
||||||
const query: PromQuery = { expr: '', refId: 'A', interval: '1s', exemplar: true };
|
|
||||||
const range: TimeRange = {
|
|
||||||
from: toUtc('2020-01-01', 'YYYY-MM-DD'),
|
|
||||||
to: toUtc('2020-01-02', 'YYYY-MM-DD'),
|
|
||||||
raw: {
|
|
||||||
from: toUtc('2020-01-01', 'YYYY-MM-DD'),
|
|
||||||
to: toUtc('2020-01-02', 'YYYY-MM-DD'),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const data: PanelData = {
|
|
||||||
state: LoadingState.NotStarted,
|
|
||||||
series: [],
|
|
||||||
request: {
|
|
||||||
requestId: '1',
|
|
||||||
dashboardId: 1,
|
|
||||||
intervalMs: 1000,
|
|
||||||
interval: '1s',
|
|
||||||
panelId: 1,
|
|
||||||
range: {
|
|
||||||
from: toUtc('2020-01-01', 'YYYY-MM-DD'),
|
|
||||||
to: toUtc('2020-01-02', 'YYYY-MM-DD'),
|
|
||||||
raw: {
|
|
||||||
from: toUtc('2020-01-01', 'YYYY-MM-DD'),
|
|
||||||
to: toUtc('2020-01-02', 'YYYY-MM-DD'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scopedVars: {},
|
|
||||||
targets: [],
|
|
||||||
timezone: 'GMT',
|
|
||||||
app: 'Grafana',
|
|
||||||
startTime: 0,
|
|
||||||
},
|
|
||||||
timeRange: {
|
|
||||||
from: toUtc('2020-01-01', 'YYYY-MM-DD'),
|
|
||||||
to: toUtc('2020-01-02', 'YYYY-MM-DD'),
|
|
||||||
raw: {
|
|
||||||
from: toUtc('2020-01-01', 'YYYY-MM-DD'),
|
|
||||||
to: toUtc('2020-01-02', 'YYYY-MM-DD'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const history: any[] = [];
|
|
||||||
const exploreMode = 'Metrics';
|
|
||||||
|
|
||||||
const props: any = {
|
|
||||||
query,
|
|
||||||
data,
|
|
||||||
range,
|
|
||||||
datasource,
|
|
||||||
exploreMode,
|
|
||||||
history,
|
|
||||||
onChange,
|
|
||||||
onRunQuery,
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.assign(props, propOverrides);
|
|
||||||
|
|
||||||
return <PromExploreQueryEditor {...props} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('PromExploreQueryEditor', () => {
|
|
||||||
it('should render component', () => {
|
|
||||||
render(setup());
|
|
||||||
expect(screen.getByTestId(testIds.editor)).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render PromQueryField with ExtraFieldElement', async () => {
|
|
||||||
render(setup());
|
|
||||||
expect(screen.getByTestId(extraFieldTestIds.extraFieldEditor)).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set default value for expr if it is undefined', async () => {
|
|
||||||
const onChange = jest.fn();
|
|
||||||
const query = { expr: undefined, exemplar: false, instant: false, range: true };
|
|
||||||
render(setup({ onChange, query }));
|
|
||||||
expect(onChange).toHaveBeenCalledTimes(1);
|
|
||||||
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ expr: '' }));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set default value for exemplars if it is undefined', async () => {
|
|
||||||
const onChange = jest.fn();
|
|
||||||
const query = { expr: '', instant: false, range: true };
|
|
||||||
render(setup({ onChange, query }));
|
|
||||||
expect(onChange).toHaveBeenCalledTimes(1);
|
|
||||||
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ exemplar: true }));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set default value for instant and range if expr is falsy', async () => {
|
|
||||||
const onChange = jest.fn();
|
|
||||||
let query = { expr: '', exemplar: true };
|
|
||||||
render(setup({ onChange, query }));
|
|
||||||
expect(onChange).toHaveBeenCalledTimes(1);
|
|
||||||
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ instant: true, range: true }));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not set default value for instant and range with truthy expr', async () => {
|
|
||||||
const onChange = jest.fn();
|
|
||||||
let query = { expr: 'foo', exemplar: true };
|
|
||||||
render(setup({ onChange, query }));
|
|
||||||
expect(onChange).toHaveBeenCalledTimes(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add default values for multiple missing values', async () => {
|
|
||||||
const onChange = jest.fn();
|
|
||||||
let query = {};
|
|
||||||
render(setup({ onChange, query }));
|
|
||||||
expect(onChange).toHaveBeenCalledTimes(3);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,54 +0,0 @@
|
|||||||
import React, { memo, useEffect } from 'react';
|
|
||||||
|
|
||||||
import { QueryEditorProps, CoreApp } from '@grafana/data';
|
|
||||||
|
|
||||||
import { PrometheusDatasource } from '../datasource';
|
|
||||||
import { PromQuery, PromOptions } from '../types';
|
|
||||||
|
|
||||||
import { PromExploreExtraField } from './PromExploreExtraField';
|
|
||||||
import PromQueryField from './PromQueryField';
|
|
||||||
|
|
||||||
export type Props = QueryEditorProps<PrometheusDatasource, PromQuery, PromOptions>;
|
|
||||||
|
|
||||||
export const PromExploreQueryEditor = memo((props: Props) => {
|
|
||||||
const { range, query, data, datasource, history, onChange, onRunQuery } = props;
|
|
||||||
|
|
||||||
// Setting default values
|
|
||||||
useEffect(() => {
|
|
||||||
if (query.expr === undefined) {
|
|
||||||
onChange({ ...query, expr: '' });
|
|
||||||
}
|
|
||||||
if (query.exemplar === undefined) {
|
|
||||||
onChange({ ...query, exemplar: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override query type to "Both" only for new queries (no query.expr).
|
|
||||||
if (!query.instant && !query.range && !query.expr) {
|
|
||||||
onChange({ ...query, instant: true, range: true });
|
|
||||||
}
|
|
||||||
}, [onChange, query]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PromQueryField
|
|
||||||
app={CoreApp.Explore}
|
|
||||||
datasource={datasource}
|
|
||||||
query={query}
|
|
||||||
range={range}
|
|
||||||
onRunQuery={onRunQuery}
|
|
||||||
onChange={onChange}
|
|
||||||
onBlur={() => {}}
|
|
||||||
history={history}
|
|
||||||
data={data}
|
|
||||||
data-testid={testIds.editor}
|
|
||||||
ExtraFieldElement={
|
|
||||||
<PromExploreExtraField query={query} onChange={onChange} datasource={datasource} onRunQuery={onRunQuery} />
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
PromExploreQueryEditor.displayName = 'PromExploreQueryEditor';
|
|
||||||
|
|
||||||
export const testIds = {
|
|
||||||
editor: 'prom-editor-explore',
|
|
||||||
};
|
|
@ -1,75 +0,0 @@
|
|||||||
import { screen, render } from '@testing-library/react';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { dateTime, CoreApp } from '@grafana/data';
|
|
||||||
|
|
||||||
import { PrometheusDatasource } from '../datasource';
|
|
||||||
import { PromQuery } from '../types';
|
|
||||||
|
|
||||||
import { PromQueryEditor, testIds } from './PromQueryEditor';
|
|
||||||
|
|
||||||
jest.mock('app/features/dashboard/services/TimeSrv', () => {
|
|
||||||
return {
|
|
||||||
getTimeSrv: () => ({
|
|
||||||
timeRange: () => ({
|
|
||||||
from: dateTime(),
|
|
||||||
to: dateTime(),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock('./monaco-query-field/MonacoQueryFieldWrapper', () => {
|
|
||||||
const fakeQueryField = () => <div>prometheus query field</div>;
|
|
||||||
return {
|
|
||||||
MonacoQueryFieldWrapper: fakeQueryField,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const setup = (propOverrides?: object) => {
|
|
||||||
const datasourceMock: unknown = {
|
|
||||||
createQuery: jest.fn((q) => q),
|
|
||||||
getPrometheusTime: jest.fn((date, roundup) => 123),
|
|
||||||
languageProvider: {
|
|
||||||
start: () => Promise.resolve([]),
|
|
||||||
syntax: () => {},
|
|
||||||
getLabelKeys: () => [],
|
|
||||||
metrics: [],
|
|
||||||
},
|
|
||||||
getInitHints: () => [],
|
|
||||||
};
|
|
||||||
const datasource: PrometheusDatasource = datasourceMock as PrometheusDatasource;
|
|
||||||
const onRunQuery = jest.fn();
|
|
||||||
const onChange = jest.fn();
|
|
||||||
const query: PromQuery = { expr: '', refId: 'A' };
|
|
||||||
|
|
||||||
const props: any = {
|
|
||||||
datasource,
|
|
||||||
onChange,
|
|
||||||
onRunQuery,
|
|
||||||
query,
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.assign(props, propOverrides);
|
|
||||||
|
|
||||||
return render(<PromQueryEditor {...props} />);
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('Render PromQueryEditor with basic options', () => {
|
|
||||||
it('should render editor', () => {
|
|
||||||
setup();
|
|
||||||
expect(screen.getByTestId(testIds.editor)).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render exemplar editor for dashboard', () => {
|
|
||||||
setup({ app: CoreApp.Dashboard });
|
|
||||||
expect(screen.getByTestId(testIds.editor)).toBeInTheDocument();
|
|
||||||
expect(screen.getByTestId(testIds.exemplar)).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not render exemplar editor for unified alerting', () => {
|
|
||||||
setup({ app: CoreApp.UnifiedAlerting });
|
|
||||||
expect(screen.getByTestId(testIds.editor)).toBeInTheDocument();
|
|
||||||
expect(screen.queryByTestId(testIds.exemplar)).not.toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,223 +0,0 @@
|
|||||||
import { map } from 'lodash';
|
|
||||||
import React, { PureComponent } from 'react';
|
|
||||||
|
|
||||||
// Types
|
|
||||||
import { CoreApp, SelectableValue } from '@grafana/data';
|
|
||||||
import { InlineFormLabel, LegacyForms, Select } from '@grafana/ui';
|
|
||||||
|
|
||||||
import { PromQuery } from '../types';
|
|
||||||
|
|
||||||
import { PromExemplarField } from './PromExemplarField';
|
|
||||||
import PromLink from './PromLink';
|
|
||||||
import PromQueryField from './PromQueryField';
|
|
||||||
import { PromQueryEditorProps } from './types';
|
|
||||||
|
|
||||||
const { Switch } = LegacyForms;
|
|
||||||
|
|
||||||
export const FORMAT_OPTIONS: Array<SelectableValue<string>> = [
|
|
||||||
{ label: 'Time series', value: 'time_series' },
|
|
||||||
{ label: 'Table', value: 'table' },
|
|
||||||
{ label: 'Heatmap', value: 'heatmap' },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const INTERVAL_FACTOR_OPTIONS: Array<SelectableValue<number>> = map([1, 2, 3, 4, 5, 10], (value: number) => ({
|
|
||||||
value,
|
|
||||||
label: '1/' + value,
|
|
||||||
}));
|
|
||||||
|
|
||||||
interface State {
|
|
||||||
legendFormat?: string;
|
|
||||||
formatOption: SelectableValue<string>;
|
|
||||||
interval?: string;
|
|
||||||
intervalFactorOption: SelectableValue<number>;
|
|
||||||
instant: boolean;
|
|
||||||
exemplar: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PromQueryEditor extends PureComponent<PromQueryEditorProps, State> {
|
|
||||||
// Query target to be modified and used for queries
|
|
||||||
query: PromQuery;
|
|
||||||
|
|
||||||
constructor(props: PromQueryEditorProps) {
|
|
||||||
super(props);
|
|
||||||
// Use default query to prevent undefined input values
|
|
||||||
const defaultQuery: Partial<PromQuery> = {
|
|
||||||
expr: '',
|
|
||||||
legendFormat: '',
|
|
||||||
interval: '',
|
|
||||||
// Set exemplar to false for alerting queries
|
|
||||||
exemplar: props.app === CoreApp.UnifiedAlerting ? false : true,
|
|
||||||
};
|
|
||||||
const query = Object.assign({}, defaultQuery, props.query);
|
|
||||||
this.query = query;
|
|
||||||
// Query target properties that are fully controlled inputs
|
|
||||||
this.state = {
|
|
||||||
// Fully controlled text inputs
|
|
||||||
interval: query.interval,
|
|
||||||
legendFormat: query.legendFormat,
|
|
||||||
// Select options
|
|
||||||
formatOption: FORMAT_OPTIONS.find((option) => option.value === query.format) || FORMAT_OPTIONS[0],
|
|
||||||
intervalFactorOption:
|
|
||||||
INTERVAL_FACTOR_OPTIONS.find((option) => option.value === query.intervalFactor) || INTERVAL_FACTOR_OPTIONS[0],
|
|
||||||
// Switch options
|
|
||||||
instant: Boolean(query.instant),
|
|
||||||
exemplar: Boolean(query.exemplar),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onFieldChange = (query: PromQuery, override?: any) => {
|
|
||||||
this.query.expr = query.expr;
|
|
||||||
};
|
|
||||||
|
|
||||||
onFormatChange = (option: SelectableValue<string>) => {
|
|
||||||
this.query.format = option.value;
|
|
||||||
this.setState({ formatOption: option }, this.onRunQuery);
|
|
||||||
};
|
|
||||||
|
|
||||||
onInstantChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
|
||||||
const instant = e.currentTarget.checked;
|
|
||||||
this.query.instant = instant;
|
|
||||||
this.setState({ instant }, this.onRunQuery);
|
|
||||||
};
|
|
||||||
|
|
||||||
onIntervalChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
|
||||||
const interval = e.currentTarget.value;
|
|
||||||
this.query.interval = interval;
|
|
||||||
this.setState({ interval });
|
|
||||||
};
|
|
||||||
|
|
||||||
onIntervalFactorChange = (option: SelectableValue<number>) => {
|
|
||||||
this.query.intervalFactor = option.value;
|
|
||||||
this.setState({ intervalFactorOption: option }, this.onRunQuery);
|
|
||||||
};
|
|
||||||
|
|
||||||
onLegendChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
|
||||||
const legendFormat = e.currentTarget.value;
|
|
||||||
this.query.legendFormat = legendFormat;
|
|
||||||
this.setState({ legendFormat });
|
|
||||||
};
|
|
||||||
|
|
||||||
onExemplarChange = (isEnabled: boolean) => {
|
|
||||||
this.query.exemplar = isEnabled;
|
|
||||||
this.setState({ exemplar: isEnabled }, this.onRunQuery);
|
|
||||||
};
|
|
||||||
|
|
||||||
onRunQuery = () => {
|
|
||||||
const { query } = this;
|
|
||||||
// Change of query.hide happens outside of this component and is just passed as prop. We have to update it when running queries.
|
|
||||||
const { hide } = this.props.query;
|
|
||||||
this.props.onChange({ ...query, hide });
|
|
||||||
this.props.onRunQuery();
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { datasource, query, range, data } = this.props;
|
|
||||||
const { formatOption, instant, interval, intervalFactorOption, legendFormat } = this.state;
|
|
||||||
//We want to hide exemplar field for unified alerting as exemplars in alerting don't make sense and are source of confusion
|
|
||||||
const showExemplarField = this.props.app !== CoreApp.UnifiedAlerting;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PromQueryField
|
|
||||||
datasource={datasource}
|
|
||||||
query={query}
|
|
||||||
range={range}
|
|
||||||
onRunQuery={this.onRunQuery}
|
|
||||||
onChange={this.onFieldChange}
|
|
||||||
history={[]}
|
|
||||||
data={data}
|
|
||||||
data-testid={testIds.editor}
|
|
||||||
ExtraFieldElement={
|
|
||||||
<div className="gf-form-inline">
|
|
||||||
<div className="gf-form">
|
|
||||||
<InlineFormLabel
|
|
||||||
width={7}
|
|
||||||
tooltip="Controls the name of the time series, using name or pattern. For example
|
|
||||||
{{hostname}} will be replaced with label value for the label hostname."
|
|
||||||
>
|
|
||||||
Legend
|
|
||||||
</InlineFormLabel>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="gf-form-input"
|
|
||||||
placeholder="legend format"
|
|
||||||
value={legendFormat}
|
|
||||||
onChange={this.onLegendChange}
|
|
||||||
onBlur={this.onRunQuery}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="gf-form">
|
|
||||||
<InlineFormLabel
|
|
||||||
width={7}
|
|
||||||
tooltip={
|
|
||||||
<>
|
|
||||||
An additional lower limit for the step parameter of the Prometheus query and for the{' '}
|
|
||||||
<code>$__interval</code> and <code>$__rate_interval</code> variables. The limit is absolute and not
|
|
||||||
modified by the "Resolution" setting.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Min step
|
|
||||||
</InlineFormLabel>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="gf-form-input width-8"
|
|
||||||
aria-label="Set lower limit for the step parameter"
|
|
||||||
placeholder={interval}
|
|
||||||
onChange={this.onIntervalChange}
|
|
||||||
onBlur={this.onRunQuery}
|
|
||||||
value={interval}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="gf-form">
|
|
||||||
<div className="gf-form-label">Resolution</div>
|
|
||||||
<Select
|
|
||||||
aria-label="Select resolution"
|
|
||||||
isSearchable={false}
|
|
||||||
options={INTERVAL_FACTOR_OPTIONS}
|
|
||||||
onChange={this.onIntervalFactorChange}
|
|
||||||
value={intervalFactorOption}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="gf-form">
|
|
||||||
<div className="gf-form-label width-7">Format</div>
|
|
||||||
<Select
|
|
||||||
className="select-container"
|
|
||||||
width={16}
|
|
||||||
isSearchable={false}
|
|
||||||
options={FORMAT_OPTIONS}
|
|
||||||
onChange={this.onFormatChange}
|
|
||||||
value={formatOption}
|
|
||||||
aria-label="Select format"
|
|
||||||
/>
|
|
||||||
<Switch label="Instant" checked={instant} onChange={this.onInstantChange} />
|
|
||||||
|
|
||||||
<InlineFormLabel width={10} tooltip="Link to Graph in Prometheus">
|
|
||||||
<PromLink
|
|
||||||
datasource={datasource}
|
|
||||||
query={this.query} // Use modified query
|
|
||||||
panelData={data}
|
|
||||||
/>
|
|
||||||
</InlineFormLabel>
|
|
||||||
</div>
|
|
||||||
{showExemplarField && (
|
|
||||||
<PromExemplarField
|
|
||||||
onChange={this.onExemplarChange}
|
|
||||||
datasource={datasource}
|
|
||||||
query={this.query}
|
|
||||||
data-testid={testIds.exemplar}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const testIds = {
|
|
||||||
editor: 'prom-editor',
|
|
||||||
exemplar: 'exemplar-editor',
|
|
||||||
};
|
|
@ -6,7 +6,6 @@ import { CoreApp } from '@grafana/data';
|
|||||||
|
|
||||||
import { PrometheusDatasource } from '../datasource';
|
import { PrometheusDatasource } from '../datasource';
|
||||||
|
|
||||||
import { testIds as regularTestIds } from './PromQueryEditor';
|
|
||||||
import { PromQueryEditorByApp } from './PromQueryEditorByApp';
|
import { PromQueryEditorByApp } from './PromQueryEditorByApp';
|
||||||
import { testIds as alertingTestIds } from './PromQueryEditorForAlerting';
|
import { testIds as alertingTestIds } from './PromQueryEditorForAlerting';
|
||||||
|
|
||||||
@ -70,10 +69,9 @@ function setup(app: CoreApp): RenderResult & { onRunQuery: jest.Mock } {
|
|||||||
|
|
||||||
describe('PromQueryEditorByApp', () => {
|
describe('PromQueryEditorByApp', () => {
|
||||||
it('should render simplified query editor for cloud alerting', () => {
|
it('should render simplified query editor for cloud alerting', () => {
|
||||||
const { getByTestId, queryByTestId } = setup(CoreApp.CloudAlerting);
|
const { getByTestId } = setup(CoreApp.CloudAlerting);
|
||||||
|
|
||||||
expect(getByTestId(alertingTestIds.editor)).toBeInTheDocument();
|
expect(getByTestId(alertingTestIds.editor)).toBeInTheDocument();
|
||||||
expect(queryByTestId(regularTestIds.editor)).toBeNull();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render editor selector for unkown apps', () => {
|
it('should render editor selector for unkown apps', () => {
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
import { CoreApp } from '@grafana/data';
|
import { CoreApp } from '@grafana/data';
|
||||||
import { config } from '@grafana/runtime';
|
|
||||||
|
|
||||||
import { PromQueryEditorSelector } from '../querybuilder/components/PromQueryEditorSelector';
|
import { PromQueryEditorSelector } from '../querybuilder/components/PromQueryEditorSelector';
|
||||||
|
|
||||||
import { PromExploreQueryEditor } from './PromExploreQueryEditor';
|
|
||||||
import { PromQueryEditor } from './PromQueryEditor';
|
|
||||||
import { PromQueryEditorForAlerting } from './PromQueryEditorForAlerting';
|
import { PromQueryEditorForAlerting } from './PromQueryEditorForAlerting';
|
||||||
import { PromQueryEditorProps } from './types';
|
import { PromQueryEditorProps } from './types';
|
||||||
|
|
||||||
@ -16,16 +13,8 @@ export function PromQueryEditorByApp(props: PromQueryEditorProps) {
|
|||||||
switch (app) {
|
switch (app) {
|
||||||
case CoreApp.CloudAlerting:
|
case CoreApp.CloudAlerting:
|
||||||
return <PromQueryEditorForAlerting {...props} />;
|
return <PromQueryEditorForAlerting {...props} />;
|
||||||
case CoreApp.Explore:
|
|
||||||
if (config.featureToggles.promQueryBuilder) {
|
|
||||||
return <PromQueryEditorSelector {...props} />;
|
|
||||||
}
|
|
||||||
return <PromExploreQueryEditor {...props} />;
|
|
||||||
default:
|
default:
|
||||||
if (config.featureToggles.promQueryBuilder) {
|
return <PromQueryEditorSelector {...props} />;
|
||||||
return <PromQueryEditorSelector {...props} />;
|
|
||||||
}
|
|
||||||
return <PromQueryEditor {...props} />;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,10 +5,10 @@ import { EditorField, EditorRow, EditorSwitch } from '@grafana/experimental';
|
|||||||
import { AutoSizeInput, RadioButtonGroup, Select } from '@grafana/ui';
|
import { AutoSizeInput, RadioButtonGroup, Select } from '@grafana/ui';
|
||||||
|
|
||||||
import { getQueryTypeChangeHandler, getQueryTypeOptions } from '../../components/PromExploreExtraField';
|
import { getQueryTypeChangeHandler, getQueryTypeOptions } from '../../components/PromExploreExtraField';
|
||||||
import { FORMAT_OPTIONS, INTERVAL_FACTOR_OPTIONS } from '../../components/PromQueryEditor';
|
|
||||||
import { PromQuery } from '../../types';
|
import { PromQuery } from '../../types';
|
||||||
import { QueryOptionGroup } from '../shared/QueryOptionGroup';
|
import { QueryOptionGroup } from '../shared/QueryOptionGroup';
|
||||||
|
|
||||||
|
import { FORMAT_OPTIONS, INTERVAL_FACTOR_OPTIONS } from './PromQueryEditorSelector';
|
||||||
import { getLegendModeLabel, PromQueryLegendEditor } from './PromQueryLegendEditor';
|
import { getLegendModeLabel, PromQueryLegendEditor } from './PromQueryLegendEditor';
|
||||||
|
|
||||||
export interface UIOptions {
|
export interface UIOptions {
|
||||||
|
@ -4,7 +4,6 @@ import React from 'react';
|
|||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { useStyles2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { testIds } from '../../components/PromQueryEditor';
|
|
||||||
import PromQueryField from '../../components/PromQueryField';
|
import PromQueryField from '../../components/PromQueryField';
|
||||||
import { PromQueryEditorProps } from '../../components/types';
|
import { PromQueryEditorProps } from '../../components/types';
|
||||||
|
|
||||||
@ -28,7 +27,6 @@ export function PromQueryCodeEditor(props: Props) {
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
history={[]}
|
history={[]}
|
||||||
data={data}
|
data={data}
|
||||||
data-testid={testIds.editor}
|
|
||||||
app={app}
|
app={app}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
import { map } from 'lodash';
|
||||||
import React, { SyntheticEvent, useCallback, useEffect, useState } from 'react';
|
import React, { SyntheticEvent, useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { CoreApp, LoadingState } from '@grafana/data';
|
import { CoreApp, LoadingState, SelectableValue } from '@grafana/data';
|
||||||
import { EditorHeader, EditorRows, FlexItem, InlineSelect, Space } from '@grafana/experimental';
|
import { EditorHeader, EditorRows, FlexItem, InlineSelect, Space } from '@grafana/experimental';
|
||||||
import { reportInteraction } from '@grafana/runtime';
|
import { reportInteraction } from '@grafana/runtime';
|
||||||
import { ConfirmModal, Button } from '@grafana/ui';
|
import { ConfirmModal, Button } from '@grafana/ui';
|
||||||
@ -19,6 +20,17 @@ import { PromQueryBuilderContainer } from './PromQueryBuilderContainer';
|
|||||||
import { PromQueryBuilderOptions } from './PromQueryBuilderOptions';
|
import { PromQueryBuilderOptions } from './PromQueryBuilderOptions';
|
||||||
import { PromQueryCodeEditor } from './PromQueryCodeEditor';
|
import { PromQueryCodeEditor } from './PromQueryCodeEditor';
|
||||||
|
|
||||||
|
export const FORMAT_OPTIONS: Array<SelectableValue<string>> = [
|
||||||
|
{ label: 'Time series', value: 'time_series' },
|
||||||
|
{ label: 'Table', value: 'table' },
|
||||||
|
{ label: 'Heatmap', value: 'heatmap' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const INTERVAL_FACTOR_OPTIONS: Array<SelectableValue<number>> = map([1, 2, 3, 4, 5, 10], (value: number) => ({
|
||||||
|
value,
|
||||||
|
label: '1/' + value,
|
||||||
|
}));
|
||||||
|
|
||||||
type Props = PromQueryEditorProps;
|
type Props = PromQueryEditorProps;
|
||||||
|
|
||||||
export const PromQueryEditorSelector = React.memo<Props>((props) => {
|
export const PromQueryEditorSelector = React.memo<Props>((props) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user