mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Loki: Add query type and line limit to query editor in dashboard (#29356)
* WIP Add line limit and query type switch toLoki dashboard editor * Refactor, reuse code for both - Explore and Dashboard * Üpdate snapshot tests * Refactor and unify * Rename test file * Update test
This commit is contained in:
parent
460883d0b2
commit
a54e0ff79d
@ -1,72 +0,0 @@
|
|||||||
// Libraries
|
|
||||||
import React, { memo } from 'react';
|
|
||||||
import { css, cx } from 'emotion';
|
|
||||||
|
|
||||||
// Types
|
|
||||||
import { InlineFormLabel, RadioButtonGroup } from '@grafana/ui';
|
|
||||||
|
|
||||||
export interface LokiExploreExtraFieldProps {
|
|
||||||
lineLimitValue: string;
|
|
||||||
queryType: string;
|
|
||||||
onLineLimitChange: (e: React.SyntheticEvent<HTMLInputElement>) => void;
|
|
||||||
onKeyDownFunc: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
||||||
onQueryTypeChange: (value: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function LokiExploreExtraField(props: LokiExploreExtraFieldProps) {
|
|
||||||
const { onLineLimitChange, onKeyDownFunc, lineLimitValue, queryType, onQueryTypeChange } = props;
|
|
||||||
|
|
||||||
const rangeOptions = [
|
|
||||||
{ value: 'range', label: 'Range' },
|
|
||||||
{ value: 'instant', label: 'Instant' },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div aria-label="Loki extra field" className="gf-form-inline">
|
|
||||||
{/*Query type field*/}
|
|
||||||
<div
|
|
||||||
data-testid="queryTypeField"
|
|
||||||
className={cx(
|
|
||||||
'gf-form explore-input-margin',
|
|
||||||
css`
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
aria-label="Query type field"
|
|
||||||
>
|
|
||||||
<InlineFormLabel
|
|
||||||
tooltip="Choose the type of query you would like to run. An instant query queries against a single point in time. A range query queries over a range of time."
|
|
||||||
width="auto"
|
|
||||||
>
|
|
||||||
Query type
|
|
||||||
</InlineFormLabel>
|
|
||||||
|
|
||||||
<RadioButtonGroup options={rangeOptions} value={queryType} onChange={onQueryTypeChange} />
|
|
||||||
</div>
|
|
||||||
{/*Line limit field*/}
|
|
||||||
<div
|
|
||||||
data-testid="lineLimitField"
|
|
||||||
className={cx(
|
|
||||||
'gf-form',
|
|
||||||
css`
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
aria-label="Line limit field"
|
|
||||||
>
|
|
||||||
<InlineFormLabel width={5}>Line limit</InlineFormLabel>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="gf-form-input width-4"
|
|
||||||
placeholder={'auto'}
|
|
||||||
min={0}
|
|
||||||
onChange={onLineLimitChange}
|
|
||||||
onKeyDown={onKeyDownFunc}
|
|
||||||
value={lineLimitValue}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default memo(LokiExploreExtraField);
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import { mount, shallow } from 'enzyme';
|
import { mount, shallow } from 'enzyme';
|
||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
import LokiExploreQueryEditor from './LokiExploreQueryEditor';
|
import LokiExploreQueryEditor from './LokiExploreQueryEditor';
|
||||||
import { LokiExploreExtraField } from './LokiExploreExtraField';
|
import { LokiOptionFields } from './LokiOptionFields';
|
||||||
import { LokiDatasource } from '../datasource';
|
import { LokiDatasource } from '../datasource';
|
||||||
import { LokiQuery } from '../types';
|
import { LokiQuery } from '../types';
|
||||||
import { ExploreMode, LoadingState, PanelData, toUtc, TimeRange } from '@grafana/data';
|
import { ExploreMode, LoadingState, PanelData, toUtc, TimeRange } from '@grafana/data';
|
||||||
@ -93,7 +93,7 @@ describe('LokiExploreQueryEditor', () => {
|
|||||||
// @ts-ignore strict null error TS2345: Argument of type '() => Promise<void>' is not assignable to parameter of type '() => void | undefined'.
|
// @ts-ignore strict null error TS2345: Argument of type '() => Promise<void>' is not assignable to parameter of type '() => void | undefined'.
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
const wrapper = setup(mount);
|
const wrapper = setup(mount);
|
||||||
expect(wrapper.find(LokiExploreExtraField).length).toBe(1);
|
expect(wrapper.find(LokiOptionFields).length).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -7,56 +7,12 @@ import { ExploreQueryFieldProps } from '@grafana/data';
|
|||||||
import { LokiDatasource } from '../datasource';
|
import { LokiDatasource } from '../datasource';
|
||||||
import { LokiQuery, LokiOptions } from '../types';
|
import { LokiQuery, LokiOptions } from '../types';
|
||||||
import { LokiQueryField } from './LokiQueryField';
|
import { LokiQueryField } from './LokiQueryField';
|
||||||
import LokiExploreExtraField from './LokiExploreExtraField';
|
|
||||||
|
|
||||||
type Props = ExploreQueryFieldProps<LokiDatasource, LokiQuery, LokiOptions>;
|
type Props = ExploreQueryFieldProps<LokiDatasource, LokiQuery, LokiOptions>;
|
||||||
|
|
||||||
export function LokiExploreQueryEditor(props: Props) {
|
export function LokiExploreQueryEditor(props: Props) {
|
||||||
const { range, query, data, datasource, history, onChange, onRunQuery } = props;
|
const { range, query, data, datasource, history, onChange, onRunQuery } = props;
|
||||||
|
|
||||||
function onChangeQueryLimit(value: string) {
|
|
||||||
const { query, onChange } = props;
|
|
||||||
const nextQuery = { ...query, maxLines: preprocessMaxLines(value) };
|
|
||||||
onChange(nextQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onQueryTypeChange(value: string) {
|
|
||||||
const { query, onChange } = props;
|
|
||||||
let nextQuery;
|
|
||||||
if (value === 'instant') {
|
|
||||||
nextQuery = { ...query, instant: true, range: false };
|
|
||||||
} else {
|
|
||||||
nextQuery = { ...query, instant: false, range: true };
|
|
||||||
}
|
|
||||||
onChange(nextQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
function preprocessMaxLines(value: string): number {
|
|
||||||
if (value.length === 0) {
|
|
||||||
// empty input - falls back to dataSource.maxLines limit
|
|
||||||
return NaN;
|
|
||||||
} else if (value.length > 0 && (isNaN(+value) || +value < 0)) {
|
|
||||||
// input with at least 1 character and that is either incorrect (value in the input field is not a number) or negative
|
|
||||||
// falls back to the limit of 0 lines
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
// default case - correct input
|
|
||||||
return +value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMaxLinesChange(e: React.SyntheticEvent<HTMLInputElement>) {
|
|
||||||
if (query.maxLines !== preprocessMaxLines(e.currentTarget.value)) {
|
|
||||||
onChangeQueryLimit(e.currentTarget.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onReturnKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
onRunQuery();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LokiQueryField
|
<LokiQueryField
|
||||||
datasource={datasource}
|
datasource={datasource}
|
||||||
@ -67,15 +23,6 @@ export function LokiExploreQueryEditor(props: Props) {
|
|||||||
history={history}
|
history={history}
|
||||||
data={data}
|
data={data}
|
||||||
range={range}
|
range={range}
|
||||||
ExtraFieldElement={
|
|
||||||
<LokiExploreExtraField
|
|
||||||
queryType={query.instant ? 'instant' : 'range'}
|
|
||||||
lineLimitValue={query?.maxLines?.toString() || ''}
|
|
||||||
onQueryTypeChange={onQueryTypeChange}
|
|
||||||
onLineLimitChange={onMaxLinesChange}
|
|
||||||
onKeyDownFunc={onReturnKeyDown}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { LokiExploreExtraFieldProps, LokiExploreExtraField } from './LokiExploreExtraField';
|
import { LokiOptionFieldsProps, LokiOptionFields } from './LokiOptionFields';
|
||||||
|
|
||||||
const setup = (propOverrides?: LokiExploreExtraFieldProps) => {
|
const setup = (propOverrides?: LokiOptionFieldsProps) => {
|
||||||
const queryType = 'range';
|
const queryType = 'range';
|
||||||
const lineLimitValue = '1';
|
const lineLimitValue = '1';
|
||||||
const onLineLimitChange = jest.fn();
|
const onLineLimitChange = jest.fn();
|
||||||
@ -19,10 +19,10 @@ const setup = (propOverrides?: LokiExploreExtraFieldProps) => {
|
|||||||
|
|
||||||
Object.assign(props, propOverrides);
|
Object.assign(props, propOverrides);
|
||||||
|
|
||||||
return render(<LokiExploreExtraField {...props} />);
|
return render(<LokiOptionFields {...props} />);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('LokiExploreExtraField', () => {
|
describe('LokiOptionFields', () => {
|
||||||
it('should render step field', () => {
|
it('should render step field', () => {
|
||||||
setup();
|
setup();
|
||||||
expect(screen.getByTestId('lineLimitField')).toBeInTheDocument();
|
expect(screen.getByTestId('lineLimitField')).toBeInTheDocument();
|
@ -0,0 +1,131 @@
|
|||||||
|
// Libraries
|
||||||
|
import React, { memo } from 'react';
|
||||||
|
import { css, cx } from 'emotion';
|
||||||
|
import { LokiQuery } from '../types';
|
||||||
|
|
||||||
|
// Types
|
||||||
|
import { InlineFormLabel, RadioButtonGroup } from '@grafana/ui';
|
||||||
|
|
||||||
|
export interface LokiOptionFieldsProps {
|
||||||
|
lineLimitValue: string;
|
||||||
|
queryType: LokiQueryType;
|
||||||
|
query: LokiQuery;
|
||||||
|
onChange: (value: LokiQuery) => void;
|
||||||
|
onRunQuery: () => void;
|
||||||
|
runOnBlur?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type LokiQueryType = 'instant' | 'range';
|
||||||
|
|
||||||
|
const queryTypeOptions = [
|
||||||
|
{ value: 'range', label: 'Range' },
|
||||||
|
{ value: 'instant', label: 'Instant' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export function LokiOptionFields(props: LokiOptionFieldsProps) {
|
||||||
|
const { lineLimitValue, queryType, query, onRunQuery, runOnBlur, onChange } = props;
|
||||||
|
|
||||||
|
function onChangeQueryLimit(value: string) {
|
||||||
|
const nextQuery = { ...query, maxLines: preprocessMaxLines(value) };
|
||||||
|
onChange(nextQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onQueryTypeChange(value: LokiQueryType) {
|
||||||
|
let nextQuery;
|
||||||
|
if (value === 'instant') {
|
||||||
|
nextQuery = { ...query, instant: true, range: false };
|
||||||
|
} else {
|
||||||
|
nextQuery = { ...query, instant: false, range: true };
|
||||||
|
}
|
||||||
|
onChange(nextQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
function preprocessMaxLines(value: string): number {
|
||||||
|
if (value.length === 0) {
|
||||||
|
// empty input - falls back to dataSource.maxLines limit
|
||||||
|
return NaN;
|
||||||
|
} else if (value.length > 0 && (isNaN(+value) || +value < 0)) {
|
||||||
|
// input with at least 1 character and that is either incorrect (value in the input field is not a number) or negative
|
||||||
|
// falls back to the limit of 0 lines
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
// default case - correct input
|
||||||
|
return +value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMaxLinesChange(e: React.SyntheticEvent<HTMLInputElement>) {
|
||||||
|
if (query.maxLines !== preprocessMaxLines(e.currentTarget.value)) {
|
||||||
|
onChangeQueryLimit(e.currentTarget.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onReturnKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
onRunQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div aria-label="Loki extra field" className="gf-form-inline">
|
||||||
|
{/*Query type field*/}
|
||||||
|
<div
|
||||||
|
data-testid="queryTypeField"
|
||||||
|
className={cx(
|
||||||
|
'gf-form explore-input-margin',
|
||||||
|
css`
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
aria-label="Query type field"
|
||||||
|
>
|
||||||
|
<InlineFormLabel
|
||||||
|
tooltip="Choose the type of query you would like to run. An instant query queries against a single point in time. A range query queries over a range of time."
|
||||||
|
width="auto"
|
||||||
|
>
|
||||||
|
Query type
|
||||||
|
</InlineFormLabel>
|
||||||
|
|
||||||
|
<RadioButtonGroup
|
||||||
|
options={queryTypeOptions}
|
||||||
|
value={queryType}
|
||||||
|
onChange={(type: LokiQueryType) => {
|
||||||
|
onQueryTypeChange(type);
|
||||||
|
if (runOnBlur) {
|
||||||
|
onRunQuery();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/*Line limit field*/}
|
||||||
|
<div
|
||||||
|
data-testid="lineLimitField"
|
||||||
|
className={cx(
|
||||||
|
'gf-form',
|
||||||
|
css`
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
aria-label="Line limit field"
|
||||||
|
>
|
||||||
|
<InlineFormLabel width={5}>Line limit</InlineFormLabel>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="gf-form-input width-4"
|
||||||
|
placeholder={'auto'}
|
||||||
|
min={0}
|
||||||
|
onChange={onMaxLinesChange}
|
||||||
|
onKeyDown={onReturnKeyDown}
|
||||||
|
value={lineLimitValue}
|
||||||
|
onBlur={() => {
|
||||||
|
if (runOnBlur) {
|
||||||
|
onRunQuery();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(LokiOptionFields);
|
@ -38,7 +38,7 @@ const setup = (propOverrides?: object) => {
|
|||||||
Object.assign(props, propOverrides);
|
Object.assign(props, propOverrides);
|
||||||
|
|
||||||
const wrapper = shallow(<LokiQueryEditor {...props} />);
|
const wrapper = shallow(<LokiQueryEditor {...props} />);
|
||||||
const instance = wrapper.instance() as LokiQueryEditor;
|
const instance = wrapper.instance();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
instance,
|
instance,
|
||||||
|
@ -1,90 +1,59 @@
|
|||||||
// Libraries
|
// Libraries
|
||||||
import React, { PureComponent } from 'react';
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { QueryEditorProps } from '@grafana/data';
|
import { QueryEditorProps } from '@grafana/data';
|
||||||
import { InlineFormLabel } from '@grafana/ui';
|
import { InlineFormLabel } from '@grafana/ui';
|
||||||
import { LokiDatasource } from '../datasource';
|
import { LokiDatasource } from '../datasource';
|
||||||
import { LokiQuery } from '../types';
|
import { LokiQuery, LokiOptions } from '../types';
|
||||||
import { LokiQueryField } from './LokiQueryField';
|
import { LokiQueryField } from './LokiQueryField';
|
||||||
|
|
||||||
type Props = QueryEditorProps<LokiDatasource, LokiQuery>;
|
type Props = QueryEditorProps<LokiDatasource, LokiQuery, LokiOptions>;
|
||||||
|
|
||||||
interface State {
|
export function LokiQueryEditor(props: Props) {
|
||||||
legendFormat: string;
|
const { range, query, data, datasource, onChange, onRunQuery } = props;
|
||||||
}
|
|
||||||
|
|
||||||
export class LokiQueryEditor extends PureComponent<Props, State> {
|
const onLegendChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
||||||
// Query target to be modified and used for queries
|
const nextQuery = { ...query, legendFormat: e.currentTarget.value };
|
||||||
query: LokiQuery;
|
onChange(nextQuery);
|
||||||
|
|
||||||
constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
// Use default query to prevent undefined input values
|
|
||||||
const defaultQuery: Partial<LokiQuery> = { expr: '', legendFormat: '' };
|
|
||||||
const query = Object.assign({}, defaultQuery, props.query);
|
|
||||||
this.query = query;
|
|
||||||
// Query target properties that are fully controlled inputs
|
|
||||||
this.state = {
|
|
||||||
// Fully controlled text inputs
|
|
||||||
legendFormat: query.legendFormat ?? '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onFieldChange = (query: LokiQuery, override?: any) => {
|
|
||||||
this.query.expr = query.expr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onLegendChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
const legendField = (
|
||||||
const legendFormat = e.currentTarget.value;
|
<div className="gf-form-inline">
|
||||||
this.query.legendFormat = legendFormat;
|
<div className="gf-form">
|
||||||
this.setState({ legendFormat });
|
<InlineFormLabel
|
||||||
};
|
width={6}
|
||||||
|
tooltip="Controls the name of the time series, using name or pattern. For example
|
||||||
onRunQuery = () => {
|
|
||||||
const { query } = this;
|
|
||||||
this.props.onChange(query);
|
|
||||||
this.props.onRunQuery();
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { datasource, query, data, range } = this.props;
|
|
||||||
const { legendFormat } = this.state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<LokiQueryField
|
|
||||||
datasource={datasource}
|
|
||||||
query={query}
|
|
||||||
onChange={this.onFieldChange}
|
|
||||||
onRunQuery={this.onRunQuery}
|
|
||||||
history={[]}
|
|
||||||
data={data}
|
|
||||||
range={range}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<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. The legend only applies to metric queries."
|
{{hostname}} will be replaced with label value for the label hostname. The legend only applies to metric queries."
|
||||||
>
|
>
|
||||||
Legend
|
Legend
|
||||||
</InlineFormLabel>
|
</InlineFormLabel>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="gf-form-input"
|
className="gf-form-input"
|
||||||
placeholder="legend format"
|
placeholder="legend format"
|
||||||
value={legendFormat}
|
value={query.legendFormat || ''}
|
||||||
onChange={this.onLegendChange}
|
onChange={onLegendChange}
|
||||||
onBlur={this.onRunQuery}
|
onBlur={onRunQuery}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
}
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LokiQueryField
|
||||||
|
datasource={datasource}
|
||||||
|
query={query}
|
||||||
|
onChange={onChange}
|
||||||
|
onRunQuery={onRunQuery}
|
||||||
|
onBlur={onRunQuery}
|
||||||
|
history={[]}
|
||||||
|
data={data}
|
||||||
|
range={range}
|
||||||
|
runOnBlur={true}
|
||||||
|
ExtraFieldElement={legendField}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LokiQueryEditor;
|
export default memo(LokiQueryEditor);
|
||||||
|
@ -23,6 +23,7 @@ import { LokiQuery, LokiOptions } from '../types';
|
|||||||
import { Grammar } from 'prismjs';
|
import { Grammar } from 'prismjs';
|
||||||
import LokiLanguageProvider, { LokiHistoryItem } from '../language_provider';
|
import LokiLanguageProvider, { LokiHistoryItem } from '../language_provider';
|
||||||
import LokiDatasource from '../datasource';
|
import LokiDatasource from '../datasource';
|
||||||
|
import LokiOptionFields from './LokiOptionFields';
|
||||||
|
|
||||||
function getChooserText(hasSyntax: boolean, hasLogLabels: boolean) {
|
function getChooserText(hasSyntax: boolean, hasLogLabels: boolean) {
|
||||||
if (!hasSyntax) {
|
if (!hasSyntax) {
|
||||||
@ -70,6 +71,7 @@ export interface LokiQueryFieldFormProps extends ExploreQueryFieldProps<LokiData
|
|||||||
onLoadOptions: (selectedOptions: CascaderOption[]) => void;
|
onLoadOptions: (selectedOptions: CascaderOption[]) => void;
|
||||||
onLabelsRefresh?: () => void;
|
onLabelsRefresh?: () => void;
|
||||||
ExtraFieldElement?: ReactNode;
|
ExtraFieldElement?: ReactNode;
|
||||||
|
runOnBlur?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormProps> {
|
export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormProps> {
|
||||||
@ -140,6 +142,7 @@ export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormPr
|
|||||||
onLoadOptions,
|
onLoadOptions,
|
||||||
onLabelsRefresh,
|
onLabelsRefresh,
|
||||||
datasource,
|
datasource,
|
||||||
|
runOnBlur,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const lokiLanguageProvider = datasource.languageProvider as LokiLanguageProvider;
|
const lokiLanguageProvider = datasource.languageProvider as LokiLanguageProvider;
|
||||||
const cleanText = datasource.languageProvider ? lokiLanguageProvider.cleanText : undefined;
|
const cleanText = datasource.languageProvider ? lokiLanguageProvider.cleanText : undefined;
|
||||||
@ -177,6 +180,14 @@ export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormPr
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<LokiOptionFields
|
||||||
|
queryType={query.instant ? 'instant' : 'range'}
|
||||||
|
lineLimitValue={query?.maxLines?.toString() || ''}
|
||||||
|
query={query}
|
||||||
|
onRunQuery={this.props.onRunQuery}
|
||||||
|
onChange={this.props.onChange}
|
||||||
|
runOnBlur={runOnBlur}
|
||||||
|
/>
|
||||||
{ExtraFieldElement}
|
{ExtraFieldElement}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -2,15 +2,6 @@
|
|||||||
|
|
||||||
exports[`LokiExploreQueryEditor should render component 1`] = `
|
exports[`LokiExploreQueryEditor should render component 1`] = `
|
||||||
<Component
|
<Component
|
||||||
ExtraFieldElement={
|
|
||||||
<Memo(LokiExploreExtraField)
|
|
||||||
lineLimitValue="0"
|
|
||||||
onKeyDownFunc={[Function]}
|
|
||||||
onLineLimitChange={[Function]}
|
|
||||||
onQueryTypeChange={[Function]}
|
|
||||||
queryType="range"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
data={
|
data={
|
||||||
Object {
|
Object {
|
||||||
"request": Object {
|
"request": Object {
|
||||||
|
@ -1,95 +1,99 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`Render LokiQueryEditor with legend should render 1`] = `
|
exports[`Render LokiQueryEditor with legend should render 1`] = `
|
||||||
<div>
|
<Component
|
||||||
<Component
|
ExtraFieldElement={
|
||||||
datasource={Object {}}
|
|
||||||
history={Array []}
|
|
||||||
onChange={[Function]}
|
|
||||||
onRunQuery={[Function]}
|
|
||||||
query={
|
|
||||||
Object {
|
|
||||||
"expr": "",
|
|
||||||
"legendFormat": "My Legend",
|
|
||||||
"refId": "A",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
range={
|
|
||||||
Object {
|
|
||||||
"from": "2020-01-01T00:00:00.000Z",
|
|
||||||
"to": "2020-01-02T00:00:00.000Z",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className="gf-form-inline"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="gf-form"
|
className="gf-form-inline"
|
||||||
>
|
>
|
||||||
<Component
|
<div
|
||||||
tooltip="Controls the name of the time series, using name or pattern. For example
|
className="gf-form"
|
||||||
{{hostname}} will be replaced with label value for the label hostname. The legend only applies to metric queries."
|
|
||||||
width={7}
|
|
||||||
>
|
>
|
||||||
Legend
|
<Unknown
|
||||||
</Component>
|
tooltip="Controls the name of the time series, using name or pattern. For example
|
||||||
<input
|
{{hostname}} will be replaced with label value for the label hostname. The legend only applies to metric queries."
|
||||||
className="gf-form-input"
|
width={6}
|
||||||
onBlur={[Function]}
|
>
|
||||||
onChange={[Function]}
|
Legend
|
||||||
placeholder="legend format"
|
</Unknown>
|
||||||
type="text"
|
<input
|
||||||
value="My Legend"
|
className="gf-form-input"
|
||||||
/>
|
onBlur={[MockFunction]}
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="legend format"
|
||||||
|
type="text"
|
||||||
|
value="My Legend"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
</div>
|
datasource={Object {}}
|
||||||
|
history={Array []}
|
||||||
|
onBlur={[MockFunction]}
|
||||||
|
onChange={[MockFunction]}
|
||||||
|
onRunQuery={[MockFunction]}
|
||||||
|
query={
|
||||||
|
Object {
|
||||||
|
"expr": "",
|
||||||
|
"legendFormat": "My Legend",
|
||||||
|
"refId": "A",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
range={
|
||||||
|
Object {
|
||||||
|
"from": "2020-01-01T00:00:00.000Z",
|
||||||
|
"to": "2020-01-02T00:00:00.000Z",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runOnBlur={true}
|
||||||
|
/>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Render LokiQueryEditor with legend should update timerange 1`] = `
|
exports[`Render LokiQueryEditor with legend should update timerange 1`] = `
|
||||||
<div>
|
<Component
|
||||||
<Component
|
ExtraFieldElement={
|
||||||
datasource={Object {}}
|
|
||||||
history={Array []}
|
|
||||||
onChange={[Function]}
|
|
||||||
onRunQuery={[Function]}
|
|
||||||
query={
|
|
||||||
Object {
|
|
||||||
"expr": "",
|
|
||||||
"legendFormat": "My Legend",
|
|
||||||
"refId": "A",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
range={
|
|
||||||
Object {
|
|
||||||
"from": "2019-01-01T00:00:00.000Z",
|
|
||||||
"to": "2020-01-02T00:00:00.000Z",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className="gf-form-inline"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="gf-form"
|
className="gf-form-inline"
|
||||||
>
|
>
|
||||||
<Component
|
<div
|
||||||
tooltip="Controls the name of the time series, using name or pattern. For example
|
className="gf-form"
|
||||||
{{hostname}} will be replaced with label value for the label hostname. The legend only applies to metric queries."
|
|
||||||
width={7}
|
|
||||||
>
|
>
|
||||||
Legend
|
<Unknown
|
||||||
</Component>
|
tooltip="Controls the name of the time series, using name or pattern. For example
|
||||||
<input
|
{{hostname}} will be replaced with label value for the label hostname. The legend only applies to metric queries."
|
||||||
className="gf-form-input"
|
width={6}
|
||||||
onBlur={[Function]}
|
>
|
||||||
onChange={[Function]}
|
Legend
|
||||||
placeholder="legend format"
|
</Unknown>
|
||||||
type="text"
|
<input
|
||||||
value="My Legend"
|
className="gf-form-input"
|
||||||
/>
|
onBlur={[MockFunction]}
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="legend format"
|
||||||
|
type="text"
|
||||||
|
value="My Legend"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
</div>
|
datasource={Object {}}
|
||||||
|
history={Array []}
|
||||||
|
onBlur={[MockFunction]}
|
||||||
|
onChange={[MockFunction]}
|
||||||
|
onRunQuery={[MockFunction]}
|
||||||
|
query={
|
||||||
|
Object {
|
||||||
|
"expr": "",
|
||||||
|
"legendFormat": "My Legend",
|
||||||
|
"refId": "A",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
range={
|
||||||
|
Object {
|
||||||
|
"from": "2019-01-01T00:00:00.000Z",
|
||||||
|
"to": "2020-01-02T00:00:00.000Z",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runOnBlur={true}
|
||||||
|
/>
|
||||||
`;
|
`;
|
||||||
|
Loading…
Reference in New Issue
Block a user