Dashboards: Add the option to toggle custom value options in the groupBy variable (#96892)

* allow options list locking in groupBy var

* refactor

* fix

* fix lint
This commit is contained in:
Victor Marin
2024-11-25 12:21:25 +02:00
committed by GitHub
parent 39e902860a
commit 2736fe0568
9 changed files with 55 additions and 3 deletions
@@ -77,6 +77,7 @@ export interface GroupByVariableModel extends VariableWithOptions {
type: 'groupby';
datasource: DataSourceRef | null;
multi: true;
allowCustomValue?: boolean;
}
export interface VariableOption {
@@ -652,6 +652,7 @@ describe('sceneVariablesSetToVariables', () => {
name: 'test',
label: 'test-label',
description: 'test-desc',
allowCustomValue: true,
datasource: { uid: 'fake-std', type: 'fake-std' },
defaultOptions: [
{
@@ -673,6 +674,7 @@ describe('sceneVariablesSetToVariables', () => {
expect(result).toHaveLength(1);
expect(result[0]).toMatchInlineSnapshot(`
{
"allowCustomValue": true,
"current": {
"text": [],
"value": [],
@@ -171,6 +171,7 @@ export function sceneVariablesSetToVariables(set: SceneVariables, keepQueryOptio
// @ts-expect-error
value: variable.state.value,
},
allowCustomValue: variable.state.allowCustomValue,
});
} else if (sceneUtils.isAdHocVariable(variable)) {
variables.push({
@@ -38,8 +38,11 @@ jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => ({
describe('GroupByVariableForm', () => {
const onDataSourceChangeMock = jest.fn();
const onDefaultOptionsChangeMock = jest.fn();
const onAllowCustomValueChangeMock = jest.fn();
const defaultProps: GroupByVariableFormProps = {
allowCustomValue: true,
onAllowCustomValueChange: onAllowCustomValueChangeMock,
onDataSourceChange: onDataSourceChangeMock,
onDefaultOptionsChange: onDefaultOptionsChangeMock,
};
@@ -55,6 +58,23 @@ describe('GroupByVariableForm', () => {
jest.clearAllMocks();
});
it('should render the form with allow custom value true', async () => {
const mockOnAllowCustomValueChange = jest.fn();
const {
renderer: { getByTestId },
} = setup({
allowCustomValue: true,
onAllowCustomValueChange: mockOnAllowCustomValueChange,
});
const allowCustomValueCheckbox = getByTestId(
selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsAllowCustomValueSwitch
);
expect(allowCustomValueCheckbox).toBeInTheDocument();
expect(allowCustomValueCheckbox).toBeChecked();
});
it('should call onDataSourceChange when changing the datasource', async () => {
const {
renderer: { getByTestId },
@@ -1,4 +1,4 @@
import { useCallback } from 'react';
import { FormEvent, useCallback } from 'react';
import { DataSourceInstanceSettings, MetricFindValue, readCSV } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
@@ -6,6 +6,7 @@ import { DataSourceRef } from '@grafana/schema';
import { Alert, CodeEditor, Field, Switch } from '@grafana/ui';
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
import { VariableCheckboxField } from './VariableCheckboxField';
import { VariableLegend } from './VariableLegend';
export interface GroupByVariableFormProps {
@@ -14,6 +15,8 @@ export interface GroupByVariableFormProps {
onDefaultOptionsChange: (options?: MetricFindValue[]) => void;
infoText?: string;
defaultOptions?: MetricFindValue[];
allowCustomValue: boolean;
onAllowCustomValueChange: (event: FormEvent<HTMLInputElement>) => void;
}
export function GroupByVariableForm({
@@ -22,6 +25,8 @@ export function GroupByVariableForm({
infoText,
onDataSourceChange,
onDefaultOptionsChange,
allowCustomValue,
onAllowCustomValueChange,
}: GroupByVariableFormProps) {
const updateDefaultOptions = useCallback(
(csvContent: string) => {
@@ -76,6 +81,14 @@ export function GroupByVariableForm({
showLineNumbers={true}
/>
)}
<VariableCheckboxField
value={allowCustomValue}
name="Allow custom values"
description="Enables users to add custom values to the list"
onChange={onAllowCustomValueChange}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsAllowCustomValueSwitch}
/>
</>
);
}
@@ -38,13 +38,18 @@ jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => ({
}));
describe('GroupByVariableEditor', () => {
it('renders AdHocVariableForm with correct props', async () => {
it('renders GroupByVariableForm with correct props', async () => {
const { renderer } = await setup();
const dataSourcePicker = renderer.getByTestId(
selectors.pages.Dashboard.Settings.Variables.Edit.GroupByVariable.dataSourceSelect
);
const infoText = renderer.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.GroupByVariable.infoText);
const allowCustomValueCheckbox = renderer.getByTestId(
selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsAllowCustomValueSwitch
);
expect(allowCustomValueCheckbox).toBeInTheDocument();
expect(allowCustomValueCheckbox).toBeChecked();
expect(dataSourcePicker).toBeInTheDocument();
expect(dataSourcePicker.getAttribute('placeholder')).toBe('Default Test Data Source');
expect(infoText).toBeInTheDocument();
@@ -1,3 +1,4 @@
import { FormEvent } from 'react';
import { useAsync } from 'react-use';
import { DataSourceInstanceSettings, MetricFindValue, getDataSourceRef } from '@grafana/data';
@@ -13,7 +14,7 @@ interface GroupByVariableEditorProps {
export function GroupByVariableEditor(props: GroupByVariableEditorProps) {
const { variable, onRunQuery } = props;
const { datasource: datasourceRef, defaultOptions } = variable.useState();
const { datasource: datasourceRef, defaultOptions, allowCustomValue = true } = variable.useState();
const { value: datasource } = useAsync(async () => {
return await getDataSourceSrv().get(datasourceRef);
@@ -35,6 +36,10 @@ export function GroupByVariableEditor(props: GroupByVariableEditorProps) {
onRunQuery();
};
const onAllowCustomValueChange = (event: FormEvent<HTMLInputElement>) => {
variable.setState({ allowCustomValue: event.currentTarget.checked });
};
return (
<GroupByVariableForm
defaultOptions={defaultOptions}
@@ -42,6 +47,8 @@ export function GroupByVariableEditor(props: GroupByVariableEditorProps) {
infoText={datasourceRef ? message : undefined}
onDataSourceChange={onDataSourceChange}
onDefaultOptionsChange={onDefaultOptionsChange}
allowCustomValue={allowCustomValue}
onAllowCustomValueChange={onAllowCustomValueChange}
/>
);
}
@@ -557,6 +557,7 @@ describe('when creating variables objects', () => {
type: 'prometheus',
},
multi: true,
allowCustomValue: true,
options: [
{
selected: false,
@@ -608,6 +609,7 @@ describe('when creating variables objects', () => {
value: [],
datasource: { uid: 'gdev-prometheus', type: 'prometheus' },
applyMode: 'auto',
allowCustomValue: true,
});
});
});
@@ -246,6 +246,7 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode
hide: variable.hide,
// @ts-expect-error
defaultOptions: variable.options,
allowCustomValue: variable.allowCustomValue ?? true,
});
} else {
throw new Error(`Scenes: Unsupported variable type ${variable.type}`);