mirror of
https://github.com/grafana/grafana.git
synced 2025-02-13 00:55:47 -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 { act } from 'react-dom/test-utils';
|
||||
import LokiExploreQueryEditor from './LokiExploreQueryEditor';
|
||||
import { LokiExploreExtraField } from './LokiExploreExtraField';
|
||||
import { LokiOptionFields } from './LokiOptionFields';
|
||||
import { LokiDatasource } from '../datasource';
|
||||
import { LokiQuery } from '../types';
|
||||
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'.
|
||||
await act(async () => {
|
||||
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 { LokiQuery, LokiOptions } from '../types';
|
||||
import { LokiQueryField } from './LokiQueryField';
|
||||
import LokiExploreExtraField from './LokiExploreExtraField';
|
||||
|
||||
type Props = ExploreQueryFieldProps<LokiDatasource, LokiQuery, LokiOptions>;
|
||||
|
||||
export function LokiExploreQueryEditor(props: 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 (
|
||||
<LokiQueryField
|
||||
datasource={datasource}
|
||||
@ -67,15 +23,6 @@ export function LokiExploreQueryEditor(props: Props) {
|
||||
history={history}
|
||||
data={data}
|
||||
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 { 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 lineLimitValue = '1';
|
||||
const onLineLimitChange = jest.fn();
|
||||
@ -19,10 +19,10 @@ const setup = (propOverrides?: LokiExploreExtraFieldProps) => {
|
||||
|
||||
Object.assign(props, propOverrides);
|
||||
|
||||
return render(<LokiExploreExtraField {...props} />);
|
||||
return render(<LokiOptionFields {...props} />);
|
||||
};
|
||||
|
||||
describe('LokiExploreExtraField', () => {
|
||||
describe('LokiOptionFields', () => {
|
||||
it('should render step field', () => {
|
||||
setup();
|
||||
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);
|
||||
|
||||
const wrapper = shallow(<LokiQueryEditor {...props} />);
|
||||
const instance = wrapper.instance() as LokiQueryEditor;
|
||||
const instance = wrapper.instance();
|
||||
|
||||
return {
|
||||
instance,
|
||||
|
@ -1,90 +1,59 @@
|
||||
// Libraries
|
||||
import React, { PureComponent } from 'react';
|
||||
import React, { memo } from 'react';
|
||||
|
||||
// Types
|
||||
import { QueryEditorProps } from '@grafana/data';
|
||||
import { InlineFormLabel } from '@grafana/ui';
|
||||
import { LokiDatasource } from '../datasource';
|
||||
import { LokiQuery } from '../types';
|
||||
import { LokiQuery, LokiOptions } from '../types';
|
||||
import { LokiQueryField } from './LokiQueryField';
|
||||
|
||||
type Props = QueryEditorProps<LokiDatasource, LokiQuery>;
|
||||
type Props = QueryEditorProps<LokiDatasource, LokiQuery, LokiOptions>;
|
||||
|
||||
interface State {
|
||||
legendFormat: string;
|
||||
}
|
||||
export function LokiQueryEditor(props: Props) {
|
||||
const { range, query, data, datasource, onChange, onRunQuery } = props;
|
||||
|
||||
export class LokiQueryEditor extends PureComponent<Props, State> {
|
||||
// Query target to be modified and used for queries
|
||||
query: LokiQuery;
|
||||
|
||||
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;
|
||||
const onLegendChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
||||
const nextQuery = { ...query, legendFormat: e.currentTarget.value };
|
||||
onChange(nextQuery);
|
||||
};
|
||||
|
||||
onLegendChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
||||
const legendFormat = e.currentTarget.value;
|
||||
this.query.legendFormat = legendFormat;
|
||||
this.setState({ legendFormat });
|
||||
};
|
||||
|
||||
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
|
||||
const legendField = (
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<InlineFormLabel
|
||||
width={6}
|
||||
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."
|
||||
>
|
||||
Legend
|
||||
</InlineFormLabel>
|
||||
<input
|
||||
type="text"
|
||||
className="gf-form-input"
|
||||
placeholder="legend format"
|
||||
value={legendFormat}
|
||||
onChange={this.onLegendChange}
|
||||
onBlur={this.onRunQuery}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
>
|
||||
Legend
|
||||
</InlineFormLabel>
|
||||
<input
|
||||
type="text"
|
||||
className="gf-form-input"
|
||||
placeholder="legend format"
|
||||
value={query.legendFormat || ''}
|
||||
onChange={onLegendChange}
|
||||
onBlur={onRunQuery}
|
||||
/>
|
||||
</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 LokiLanguageProvider, { LokiHistoryItem } from '../language_provider';
|
||||
import LokiDatasource from '../datasource';
|
||||
import LokiOptionFields from './LokiOptionFields';
|
||||
|
||||
function getChooserText(hasSyntax: boolean, hasLogLabels: boolean) {
|
||||
if (!hasSyntax) {
|
||||
@ -70,6 +71,7 @@ export interface LokiQueryFieldFormProps extends ExploreQueryFieldProps<LokiData
|
||||
onLoadOptions: (selectedOptions: CascaderOption[]) => void;
|
||||
onLabelsRefresh?: () => void;
|
||||
ExtraFieldElement?: ReactNode;
|
||||
runOnBlur?: boolean;
|
||||
}
|
||||
|
||||
export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormProps> {
|
||||
@ -140,6 +142,7 @@ export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormPr
|
||||
onLoadOptions,
|
||||
onLabelsRefresh,
|
||||
datasource,
|
||||
runOnBlur,
|
||||
} = this.props;
|
||||
const lokiLanguageProvider = datasource.languageProvider as LokiLanguageProvider;
|
||||
const cleanText = datasource.languageProvider ? lokiLanguageProvider.cleanText : undefined;
|
||||
@ -177,6 +180,14 @@ export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormPr
|
||||
/>
|
||||
</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}
|
||||
</>
|
||||
);
|
||||
|
@ -2,15 +2,6 @@
|
||||
|
||||
exports[`LokiExploreQueryEditor should render component 1`] = `
|
||||
<Component
|
||||
ExtraFieldElement={
|
||||
<Memo(LokiExploreExtraField)
|
||||
lineLimitValue="0"
|
||||
onKeyDownFunc={[Function]}
|
||||
onLineLimitChange={[Function]}
|
||||
onQueryTypeChange={[Function]}
|
||||
queryType="range"
|
||||
/>
|
||||
}
|
||||
data={
|
||||
Object {
|
||||
"request": Object {
|
||||
|
@ -1,95 +1,99 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Render LokiQueryEditor with legend should render 1`] = `
|
||||
<div>
|
||||
<Component
|
||||
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"
|
||||
>
|
||||
<Component
|
||||
ExtraFieldElement={
|
||||
<div
|
||||
className="gf-form"
|
||||
className="gf-form-inline"
|
||||
>
|
||||
<Component
|
||||
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."
|
||||
width={7}
|
||||
<div
|
||||
className="gf-form"
|
||||
>
|
||||
Legend
|
||||
</Component>
|
||||
<input
|
||||
className="gf-form-input"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder="legend format"
|
||||
type="text"
|
||||
value="My Legend"
|
||||
/>
|
||||
<Unknown
|
||||
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."
|
||||
width={6}
|
||||
>
|
||||
Legend
|
||||
</Unknown>
|
||||
<input
|
||||
className="gf-form-input"
|
||||
onBlur={[MockFunction]}
|
||||
onChange={[Function]}
|
||||
placeholder="legend format"
|
||||
type="text"
|
||||
value="My Legend"
|
||||
/>
|
||||
</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`] = `
|
||||
<div>
|
||||
<Component
|
||||
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"
|
||||
>
|
||||
<Component
|
||||
ExtraFieldElement={
|
||||
<div
|
||||
className="gf-form"
|
||||
className="gf-form-inline"
|
||||
>
|
||||
<Component
|
||||
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."
|
||||
width={7}
|
||||
<div
|
||||
className="gf-form"
|
||||
>
|
||||
Legend
|
||||
</Component>
|
||||
<input
|
||||
className="gf-form-input"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder="legend format"
|
||||
type="text"
|
||||
value="My Legend"
|
||||
/>
|
||||
<Unknown
|
||||
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."
|
||||
width={6}
|
||||
>
|
||||
Legend
|
||||
</Unknown>
|
||||
<input
|
||||
className="gf-form-input"
|
||||
onBlur={[MockFunction]}
|
||||
onChange={[Function]}
|
||||
placeholder="legend format"
|
||||
type="text"
|
||||
value="My Legend"
|
||||
/>
|
||||
</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