mirror of
https://github.com/grafana/grafana.git
synced 2024-12-02 05:29:42 -06:00
Dashboard: Migration - EditVariable Settings: Implement Constant Variable (#80743)
Co-authored-by: Ivan Ortega <ivanortegaalba@gmail.com>
This commit is contained in:
parent
80395e43d8
commit
4b113f87f9
@ -43,6 +43,7 @@ export function VariableEditorForm({ variable, onTypeChange, onGoBack, onDiscard
|
||||
const onDescriptionBlur = (e: FormEvent<HTMLTextAreaElement>) =>
|
||||
variable.setState({ description: e.currentTarget.value });
|
||||
const onHideChange = (hide: VariableHide) => variable.setState({ hide });
|
||||
const isHasVariableOptions = hasVariableOptions(variable);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -80,7 +81,7 @@ export function VariableEditorForm({ variable, onTypeChange, onGoBack, onDiscard
|
||||
|
||||
{EditorToRender && <EditorToRender variable={variable} onRunQuery={onRunQuery} />}
|
||||
|
||||
{hasVariableOptions(variable) && <VariableValuesPreview options={variable.getOptionsForSelect()} />}
|
||||
{isHasVariableOptions && <VariableValuesPreview options={variable.getOptionsForSelect()} />}
|
||||
|
||||
<div style={{ marginTop: '16px' }}>
|
||||
<HorizontalGroup spacing="md" height="inherit">
|
||||
@ -94,14 +95,17 @@ export function VariableEditorForm({ variable, onTypeChange, onGoBack, onDiscard
|
||||
>
|
||||
Back to list
|
||||
</Button>
|
||||
<Button
|
||||
disabled={runQueryState.loading}
|
||||
variant="secondary"
|
||||
data-testid={selectors.pages.Dashboard.Settings.Variables.Edit.General.submitButton}
|
||||
onClick={onRunQuery}
|
||||
>
|
||||
{runQueryState.loading ? <LoadingPlaceholder text="Running query..." /> : `Run query`}
|
||||
</Button>
|
||||
|
||||
{isHasVariableOptions && (
|
||||
<Button
|
||||
disabled={runQueryState.loading}
|
||||
variant="secondary"
|
||||
data-testid={selectors.pages.Dashboard.Settings.Variables.Edit.General.submitButton}
|
||||
onClick={onRunQuery}
|
||||
>
|
||||
{runQueryState.loading ? <LoadingPlaceholder text="Running query..." /> : `Run query`}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="destructive"
|
||||
data-testid={selectors.pages.Dashboard.Settings.Variables.Edit.General.applyButton}
|
||||
|
@ -5,9 +5,10 @@ import { Draggable } from 'react-beautiful-dnd';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { reportInteraction } from '@grafana/runtime';
|
||||
import { QueryVariable, SceneVariable } from '@grafana/scenes';
|
||||
import { SceneVariable } from '@grafana/scenes';
|
||||
import { Button, ConfirmModal, Icon, IconButton, useStyles2, useTheme2 } from '@grafana/ui';
|
||||
import { hasOptions } from 'app/features/variables/guard';
|
||||
|
||||
import { getDefinition } from './utils';
|
||||
|
||||
export interface VariableEditorListRowProps {
|
||||
index: number;
|
||||
@ -121,20 +122,6 @@ export function VariableEditorListRow({
|
||||
);
|
||||
}
|
||||
|
||||
function getDefinition(model: SceneVariable): string {
|
||||
let definition = '';
|
||||
if (model instanceof QueryVariable) {
|
||||
if (model.state.definition) {
|
||||
definition = model.state.definition;
|
||||
} else if (typeof model.state.query === 'string') {
|
||||
definition = model.state.query;
|
||||
}
|
||||
} else if (hasOptions(model.state)) {
|
||||
definition = model.state.query;
|
||||
}
|
||||
return definition;
|
||||
}
|
||||
|
||||
function getStyles(theme: GrafanaTheme2) {
|
||||
return {
|
||||
dragHandle: css({
|
||||
|
@ -0,0 +1,27 @@
|
||||
import React, { FormEvent } from 'react';
|
||||
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
import { VariableLegend } from './VariableLegend';
|
||||
import { VariableTextField } from './VariableTextField';
|
||||
|
||||
interface ConstantVariableFormProps {
|
||||
constantValue: string;
|
||||
onChange: (event: FormEvent<HTMLInputElement>) => void;
|
||||
}
|
||||
|
||||
export function ConstantVariableForm({ onChange, constantValue }: ConstantVariableFormProps) {
|
||||
return (
|
||||
<>
|
||||
<VariableLegend>Constant options</VariableLegend>
|
||||
<VariableTextField
|
||||
defaultValue={constantValue}
|
||||
name="Value"
|
||||
placeholder="your metric prefix"
|
||||
onBlur={onChange}
|
||||
testId={selectors.pages.Dashboard.Settings.Variables.Edit.ConstantVariable.constantOptionsQueryInputV2}
|
||||
width={30}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
|
||||
import { ConstantVariable } from '@grafana/scenes';
|
||||
|
||||
import { ConstantVariableEditor } from './ConstantVariableEditor';
|
||||
|
||||
describe('ConstantVariableEditor', () => {
|
||||
let constantVar: ConstantVariable;
|
||||
beforeEach(async () => {
|
||||
const result = await buildTestScene();
|
||||
constantVar = result.constantVar;
|
||||
});
|
||||
|
||||
it('renders constant value', () => {
|
||||
render(<ConstantVariableEditor variable={constantVar} />);
|
||||
const input = screen.getByRole('textbox', { name: 'Value' });
|
||||
expect(input).toBeInTheDocument();
|
||||
expect(input).toHaveValue('constant value');
|
||||
});
|
||||
|
||||
it('changes the value', async () => {
|
||||
render(<ConstantVariableEditor variable={constantVar} />);
|
||||
|
||||
const input = screen.getByRole('textbox', { name: 'Value' });
|
||||
expect(input).toBeInTheDocument();
|
||||
expect(input).toHaveValue('constant value');
|
||||
|
||||
// change input value
|
||||
const newValue = 'new constant value';
|
||||
await userEvent.clear(input);
|
||||
await userEvent.type(input, newValue);
|
||||
|
||||
expect(input).toHaveValue(newValue);
|
||||
|
||||
await userEvent.tab();
|
||||
expect(constantVar.state.value).toBe(newValue);
|
||||
});
|
||||
});
|
||||
|
||||
async function buildTestScene() {
|
||||
const constantVar = new ConstantVariable({
|
||||
name: 'constantVar',
|
||||
type: 'constant',
|
||||
value: 'constant value',
|
||||
});
|
||||
|
||||
return { constantVar };
|
||||
}
|
@ -2,11 +2,18 @@ import React from 'react';
|
||||
|
||||
import { ConstantVariable } from '@grafana/scenes';
|
||||
|
||||
import { ConstantVariableForm } from '../components/ConstantVariableForm';
|
||||
|
||||
interface ConstantVariableEditorProps {
|
||||
variable: ConstantVariable;
|
||||
onChange: (variable: ConstantVariable) => void;
|
||||
}
|
||||
|
||||
export function ConstantVariableEditor(props: ConstantVariableEditorProps) {
|
||||
return <div>ConstantVariableEditor</div>;
|
||||
export function ConstantVariableEditor({ variable }: ConstantVariableEditorProps) {
|
||||
const { value } = variable.useState();
|
||||
|
||||
const onConstantValueChange = (event: React.FormEvent<HTMLInputElement>) => {
|
||||
variable.setState({ value: event.currentTarget.value });
|
||||
};
|
||||
|
||||
return <ConstantVariableForm constantValue={String(value)} onChange={onConstantValueChange} />;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import {
|
||||
getVariableScene,
|
||||
hasVariableOptions,
|
||||
EditableVariableType,
|
||||
getDefinition,
|
||||
} from './utils';
|
||||
|
||||
const templateSrv = {
|
||||
@ -138,3 +139,64 @@ describe('hasVariableOptions', () => {
|
||||
expect(hasVariableOptions(variableWithoutOptions)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDefinition', () => {
|
||||
it('returns the correct definition for QueryVariable when definition is defined', () => {
|
||||
const model = new QueryVariable({
|
||||
name: 'custom0',
|
||||
query: '',
|
||||
definition: 'legacy ABC query definition',
|
||||
});
|
||||
expect(getDefinition(model)).toBe('legacy ABC query definition');
|
||||
});
|
||||
|
||||
it('returns the correct definition for QueryVariable when definition is not defined', () => {
|
||||
const model = new QueryVariable({
|
||||
name: 'custom0',
|
||||
query: 'ABC query',
|
||||
definition: '',
|
||||
});
|
||||
expect(getDefinition(model)).toBe('ABC query');
|
||||
});
|
||||
|
||||
it('returns the correct definition for DataSourceVariable', () => {
|
||||
const model = new DataSourceVariable({
|
||||
name: 'ds0',
|
||||
pluginId: 'datasource-plugin',
|
||||
value: 'datasource-value',
|
||||
});
|
||||
expect(getDefinition(model)).toBe('datasource-plugin');
|
||||
});
|
||||
|
||||
it('returns the correct definition for CustomVariable', () => {
|
||||
const model = new CustomVariable({
|
||||
name: 'custom0',
|
||||
query: 'Custom, A, B, C',
|
||||
});
|
||||
expect(getDefinition(model)).toBe('Custom, A, B, C');
|
||||
});
|
||||
|
||||
it('returns the correct definition for IntervalVariable', () => {
|
||||
const model = new IntervalVariable({
|
||||
name: 'interval0',
|
||||
intervals: ['1m', '5m', '15m', '30m', '1h', '6h', '12h', '1d'],
|
||||
});
|
||||
expect(getDefinition(model)).toBe('1m,5m,15m,30m,1h,6h,12h,1d');
|
||||
});
|
||||
|
||||
it('returns the correct definition for TextBoxVariable', () => {
|
||||
const model = new TextBoxVariable({
|
||||
name: 'textbox0',
|
||||
value: 'TextBox Value',
|
||||
});
|
||||
expect(getDefinition(model)).toBe('TextBox Value');
|
||||
});
|
||||
|
||||
it('returns the correct definition for ConstantVariable', () => {
|
||||
const model = new ConstantVariable({
|
||||
name: 'constant0',
|
||||
value: 'Constant Value',
|
||||
});
|
||||
expect(getDefinition(model)).toBe('Constant Value');
|
||||
});
|
||||
});
|
||||
|
@ -12,6 +12,8 @@ import {
|
||||
} from '@grafana/scenes';
|
||||
import { VariableType } from '@grafana/schema';
|
||||
|
||||
import { getIntervalsQueryFromNewIntervalModel } from '../../utils/utils';
|
||||
|
||||
import { AdHocFiltersVariableEditor } from './editors/AdHocFiltersVariableEditor';
|
||||
import { ConstantVariableEditor } from './editors/ConstantVariableEditor';
|
||||
import { CustomVariableEditor } from './editors/CustomVariableEditor';
|
||||
@ -120,3 +122,21 @@ export function getVariableScene(type: EditableVariableType, initialState: Commo
|
||||
export function hasVariableOptions(variable: SceneVariable): variable is MultiValueVariable {
|
||||
return 'options' in variable.state;
|
||||
}
|
||||
|
||||
export function getDefinition(model: SceneVariable): string {
|
||||
let definition = '';
|
||||
|
||||
if (model instanceof QueryVariable) {
|
||||
definition = model.state.definition || (typeof model.state.query === 'string' ? model.state.query : '');
|
||||
} else if (model instanceof DataSourceVariable) {
|
||||
definition = String(model.state.pluginId);
|
||||
} else if (model instanceof CustomVariable) {
|
||||
definition = model.state.query;
|
||||
} else if (model instanceof IntervalVariable) {
|
||||
definition = getIntervalsQueryFromNewIntervalModel(model.state.intervals);
|
||||
} else if (model instanceof TextBoxVariable || model instanceof ConstantVariable) {
|
||||
definition = String(model.state.value);
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
import React, { FormEvent, PureComponent } from 'react';
|
||||
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { ConstantVariableForm } from 'app/features/dashboard-scene/settings/variables/components/ConstantVariableForm';
|
||||
|
||||
import { VariableLegend } from '../../dashboard-scene/settings/variables/components/VariableLegend';
|
||||
import { VariableTextField } from '../../dashboard-scene/settings/variables/components/VariableTextField';
|
||||
import { VariableEditorProps } from '../editor/types';
|
||||
import { ConstantVariableModel } from '../types';
|
||||
|
||||
@ -11,13 +9,6 @@ export interface Props extends VariableEditorProps<ConstantVariableModel> {}
|
||||
|
||||
export class ConstantVariableEditor extends PureComponent<Props> {
|
||||
onChange = (event: FormEvent<HTMLInputElement>) => {
|
||||
this.props.onPropChange({
|
||||
propName: 'query',
|
||||
propValue: event.currentTarget.value,
|
||||
});
|
||||
};
|
||||
|
||||
onBlur = (event: FormEvent<HTMLInputElement>) => {
|
||||
this.props.onPropChange({
|
||||
propName: 'query',
|
||||
propValue: event.currentTarget.value,
|
||||
@ -26,19 +17,6 @@ export class ConstantVariableEditor extends PureComponent<Props> {
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<VariableLegend>Constant options</VariableLegend>
|
||||
<VariableTextField
|
||||
value={this.props.variable.query}
|
||||
name="Value"
|
||||
placeholder="your metric prefix"
|
||||
onChange={this.onChange}
|
||||
onBlur={this.onBlur}
|
||||
testId={selectors.pages.Dashboard.Settings.Variables.Edit.ConstantVariable.constantOptionsQueryInputV2}
|
||||
width={30}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
return <ConstantVariableForm constantValue={this.props.variable.query} onChange={this.onChange} />;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user