mirror of
https://github.com/grafana/grafana.git
synced 2025-09-26 05:44:18 +08:00
Prometheus/Explore: Update position of fields in editor (#27816)
* Update position of buttons * Refactor, add tests * Pass onKeydown func * Update public/app/plugins/datasource/prometheus/components/PromQueryField.tsx Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com> Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>
This commit is contained in:
@ -1,28 +1,35 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { PromExploreExtraField, PromExploreExtraFieldProps } from './PromExploreExtraField';
|
import { PromExploreExtraFieldProps, PromExploreExtraField } from './PromExploreExtraField';
|
||||||
|
|
||||||
const setup = (propOverrides?: PromExploreExtraFieldProps) => {
|
const setup = (propOverrides?: PromExploreExtraFieldProps) => {
|
||||||
const label = 'Prometheus Explore Extra Field';
|
const queryType = 'range';
|
||||||
const value = '123';
|
const stepValue = '1';
|
||||||
const onChangeFunc = jest.fn();
|
const onStepChange = jest.fn();
|
||||||
|
const onQueryTypeChange = jest.fn();
|
||||||
const onKeyDownFunc = jest.fn();
|
const onKeyDownFunc = jest.fn();
|
||||||
|
|
||||||
const props: any = {
|
const props: any = {
|
||||||
label,
|
queryType,
|
||||||
value,
|
stepValue,
|
||||||
onChangeFunc,
|
onStepChange,
|
||||||
|
onQueryTypeChange,
|
||||||
onKeyDownFunc,
|
onKeyDownFunc,
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.assign(props, propOverrides);
|
Object.assign(props, propOverrides);
|
||||||
|
|
||||||
return shallow(<PromExploreExtraField {...props} />);
|
return render(<PromExploreExtraField {...props} />);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('PrometheusExploreExtraField', () => {
|
describe('PromExploreExtraField', () => {
|
||||||
it('should render component', () => {
|
it('should render step field', () => {
|
||||||
const wrapper = setup();
|
setup();
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(screen.getByTestId('stepField')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render query type field', () => {
|
||||||
|
setup();
|
||||||
|
expect(screen.getByTestId('queryTypeField')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,38 +1,72 @@
|
|||||||
// Libraries
|
// Libraries
|
||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
|
import { css, cx } from 'emotion';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { InlineFormLabel } from '@grafana/ui';
|
import { InlineFormLabel, RadioButtonGroup } from '@grafana/ui';
|
||||||
|
|
||||||
export interface PromExploreExtraFieldProps {
|
export interface PromExploreExtraFieldProps {
|
||||||
label: string;
|
queryType: string;
|
||||||
onChangeFunc: (e: React.SyntheticEvent<HTMLInputElement>) => void;
|
stepValue: string;
|
||||||
|
onStepChange: (e: React.SyntheticEvent<HTMLInputElement>) => void;
|
||||||
onKeyDownFunc: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
onKeyDownFunc: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
||||||
value: string;
|
onQueryTypeChange: (value: string) => void;
|
||||||
hasTooltip?: boolean;
|
|
||||||
tooltipContent?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PromExploreExtraField(props: PromExploreExtraFieldProps) {
|
export const PromExploreExtraField: React.FC<PromExploreExtraFieldProps> = memo(
|
||||||
const { label, onChangeFunc, onKeyDownFunc, value, hasTooltip, tooltipContent } = props;
|
({ queryType, stepValue, onStepChange, onQueryTypeChange, onKeyDownFunc }) => {
|
||||||
|
const rangeOptions = [
|
||||||
|
{ value: 'range', label: 'Range' },
|
||||||
|
{ value: 'instant', label: 'Instant' },
|
||||||
|
{ value: 'both', label: 'Both' },
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="gf-form-inline" aria-label="Prometheus extra field">
|
<div aria-label="Prometheus extra field" className="gf-form-inline">
|
||||||
<div className="gf-form">
|
{/*QueryTypeField */}
|
||||||
<InlineFormLabel width={5} tooltip={hasTooltip ? tooltipContent : undefined}>
|
<div
|
||||||
{label}
|
data-testid="queryTypeField"
|
||||||
|
className={cx(
|
||||||
|
'gf-form explore-input-margin',
|
||||||
|
css`
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
aria-label="Query type field"
|
||||||
|
>
|
||||||
|
<InlineFormLabel width={5}>Query type</InlineFormLabel>
|
||||||
|
|
||||||
|
<RadioButtonGroup options={rangeOptions} value={queryType} onChange={onQueryTypeChange} />
|
||||||
|
</div>
|
||||||
|
{/*Step field*/}
|
||||||
|
<div
|
||||||
|
data-testid="stepField"
|
||||||
|
className={cx(
|
||||||
|
'gf-form',
|
||||||
|
css`
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
aria-label="Step field"
|
||||||
|
>
|
||||||
|
<InlineFormLabel
|
||||||
|
width={5}
|
||||||
|
tooltip={
|
||||||
|
'Time units can be used here, for example: 5s, 1m, 3h, 1d, 1y (Default if no unit is specified: s)'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Step
|
||||||
</InlineFormLabel>
|
</InlineFormLabel>
|
||||||
<input
|
<input
|
||||||
type={'text'}
|
type={'text'}
|
||||||
className="gf-form-input width-4"
|
className="gf-form-input width-4"
|
||||||
placeholder={'auto'}
|
placeholder={'auto'}
|
||||||
onChange={onChangeFunc}
|
onChange={onStepChange}
|
||||||
onKeyDown={onKeyDownFunc}
|
onKeyDown={onKeyDownFunc}
|
||||||
value={value}
|
value={stepValue}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
export default memo(PromExploreExtraField);
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import React, { memo, FC } from 'react';
|
import React, { memo, FC } from 'react';
|
||||||
import { css } from 'emotion';
|
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { ExploreQueryFieldProps } from '@grafana/data';
|
import { ExploreQueryFieldProps } from '@grafana/data';
|
||||||
import { RadioButtonGroup } from '@grafana/ui';
|
|
||||||
|
|
||||||
import { PrometheusDatasource } from '../datasource';
|
import { PrometheusDatasource } from '../datasource';
|
||||||
import { PromQuery, PromOptions } from '../types';
|
import { PromQuery, PromOptions } from '../types';
|
||||||
@ -28,6 +26,12 @@ export const PromExploreQueryEditor: FC<Props> = (props: Props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onReturnKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
|
||||||
|
if (e.key === 'Enter' && (e.shiftKey || e.ctrlKey)) {
|
||||||
|
onRunQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onQueryTypeChange(value: string) {
|
function onQueryTypeChange(value: string) {
|
||||||
const { query, onChange } = props;
|
const { query, onChange } = props;
|
||||||
let nextQuery;
|
let nextQuery;
|
||||||
@ -41,14 +45,7 @@ export const PromExploreQueryEditor: FC<Props> = (props: Props) => {
|
|||||||
onChange(nextQuery);
|
onChange(nextQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onReturnKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
onRunQuery();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<PromQueryField
|
<PromQueryField
|
||||||
datasource={datasource}
|
datasource={datasource}
|
||||||
query={query}
|
query={query}
|
||||||
@ -59,51 +56,14 @@ export const PromExploreQueryEditor: FC<Props> = (props: Props) => {
|
|||||||
data={data}
|
data={data}
|
||||||
ExtraFieldElement={
|
ExtraFieldElement={
|
||||||
<PromExploreExtraField
|
<PromExploreExtraField
|
||||||
label={'Step'}
|
queryType={query.range && query.instant ? 'both' : query.instant ? 'instant' : 'range'}
|
||||||
onChangeFunc={onStepChange}
|
stepValue={query.interval || ''}
|
||||||
onKeyDownFunc={onReturnKeyDown}
|
|
||||||
value={query.interval || ''}
|
|
||||||
hasTooltip={true}
|
|
||||||
tooltipContent={
|
|
||||||
'Time units can be used here, for example: 5s, 1m, 3h, 1d, 1y (Default if no unit is specified: s)'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<PromExploreRadioButton
|
|
||||||
selected={query.range && query.instant ? 'both' : query.instant ? 'instant' : 'range'}
|
|
||||||
onQueryTypeChange={onQueryTypeChange}
|
onQueryTypeChange={onQueryTypeChange}
|
||||||
|
onStepChange={onStepChange}
|
||||||
|
onKeyDownFunc={onReturnKeyDown}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
type PromExploreRadioButtonProps = {
|
|
||||||
selected: string;
|
|
||||||
onQueryTypeChange: (value: string) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const PromExploreRadioButton: React.FunctionComponent<PromExploreRadioButtonProps> = ({
|
|
||||||
selected,
|
|
||||||
onQueryTypeChange,
|
|
||||||
}) => {
|
|
||||||
const rangeOptions = [
|
|
||||||
{ value: 'range', label: 'Range' },
|
|
||||||
{ value: 'instant', label: 'Instant' },
|
|
||||||
{ value: 'both', label: 'Both' },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={css`
|
|
||||||
display: flex;
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
<button className={`gf-form-label gf-form-label--btn width-5`}>
|
|
||||||
<span className="btn-title">Query type</span>
|
|
||||||
</button>
|
|
||||||
<RadioButtonGroup options={rangeOptions} value={selected} onChange={onQueryTypeChange} />
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
|||||||
{chooserText}
|
{chooserText}
|
||||||
</ButtonCascader>
|
</ButtonCascader>
|
||||||
</div>
|
</div>
|
||||||
<div className={'gf-form gf-form--grow flex-shrink-1 min-width-15 explore-input-margin'}>
|
<div className="gf-form gf-form--grow flex-shrink-1 min-width-15">
|
||||||
<QueryField
|
<QueryField
|
||||||
additionalPlugins={this.plugins}
|
additionalPlugins={this.plugins}
|
||||||
cleanText={cleanText}
|
cleanText={cleanText}
|
||||||
@ -346,8 +346,8 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
|||||||
syntaxLoaded={syntaxLoaded}
|
syntaxLoaded={syntaxLoaded}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{ExtraFieldElement}
|
|
||||||
</div>
|
</div>
|
||||||
|
{ExtraFieldElement}
|
||||||
{hint ? (
|
{hint ? (
|
||||||
<div className="query-row-break">
|
<div className="query-row-break">
|
||||||
<div className="prom-query-field-info text-warning">
|
<div className="prom-query-field-info text-warning">
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`PrometheusExploreExtraField should render component 1`] = `
|
|
||||||
<div
|
|
||||||
aria-label="Prometheus extra field"
|
|
||||||
className="gf-form-inline"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="gf-form"
|
|
||||||
>
|
|
||||||
<Component
|
|
||||||
width={5}
|
|
||||||
>
|
|
||||||
Prometheus Explore Extra Field
|
|
||||||
</Component>
|
|
||||||
<input
|
|
||||||
className="gf-form-input width-4"
|
|
||||||
onChange={[MockFunction]}
|
|
||||||
onKeyDown={[MockFunction]}
|
|
||||||
placeholder="auto"
|
|
||||||
type="text"
|
|
||||||
value="123"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
@ -1,16 +1,14 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`PromExploreQueryEditor should render component 1`] = `
|
exports[`PromExploreQueryEditor should render component 1`] = `
|
||||||
<Fragment>
|
|
||||||
<PromQueryField
|
<PromQueryField
|
||||||
ExtraFieldElement={
|
ExtraFieldElement={
|
||||||
<PromExploreExtraField
|
<Memo
|
||||||
hasTooltip={true}
|
|
||||||
label="Step"
|
|
||||||
onChangeFunc={[Function]}
|
|
||||||
onKeyDownFunc={[Function]}
|
onKeyDownFunc={[Function]}
|
||||||
tooltipContent="Time units can be used here, for example: 5s, 1m, 3h, 1d, 1y (Default if no unit is specified: s)"
|
onQueryTypeChange={[Function]}
|
||||||
value="1s"
|
onStepChange={[Function]}
|
||||||
|
queryType="range"
|
||||||
|
stepValue="1s"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
data={
|
data={
|
||||||
@ -60,9 +58,4 @@ exports[`PromExploreQueryEditor should render component 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<PromExploreRadioButton
|
|
||||||
onQueryTypeChange={[Function]}
|
|
||||||
selected="range"
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
`;
|
`;
|
||||||
|
Reference in New Issue
Block a user