mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: allows clearing the datasource selection in rule list (#41264)
This commit is contained in:
@@ -39,6 +39,8 @@
|
||||
"@grafana/tsconfig": "^1.0.0-rc1",
|
||||
"@rollup/plugin-commonjs": "21.0.1",
|
||||
"@rollup/plugin-node-resolve": "13.0.6",
|
||||
"@testing-library/react": "^12.1.2",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/angular": "1.6.56",
|
||||
"@types/history": "^4.7.8",
|
||||
"@types/jest": "27.0.2",
|
||||
|
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import { DataSourcePicker } from './DataSourcePicker';
|
||||
import { render } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
jest.mock('../services/dataSourceSrv');
|
||||
|
||||
describe('DataSourcePicker', () => {
|
||||
describe('onClear', () => {
|
||||
it('should call onClear when function is passed', async () => {
|
||||
const onClear = jest.fn();
|
||||
const select = render(<DataSourcePicker onClear={onClear} />);
|
||||
|
||||
const clearButton = select.getByLabelText('select-clear-value');
|
||||
userEvent.click(clearButton);
|
||||
expect(onClear).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not render clear button when no onClear function is passed', async () => {
|
||||
const select = render(<DataSourcePicker />);
|
||||
|
||||
expect(() => {
|
||||
select.getByLabelText('select-clear-value');
|
||||
}).toThrowError();
|
||||
});
|
||||
});
|
||||
});
|
@@ -2,7 +2,7 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Components
|
||||
import { HorizontalGroup, PluginSignatureBadge, Select, stylesFactory } from '@grafana/ui';
|
||||
import { ActionMeta, HorizontalGroup, PluginSignatureBadge, Select, stylesFactory } from '@grafana/ui';
|
||||
import {
|
||||
DataSourceInstanceSettings,
|
||||
DataSourceRef,
|
||||
@@ -40,6 +40,7 @@ export interface DataSourcePickerProps {
|
||||
noDefault?: boolean;
|
||||
width?: number;
|
||||
filter?: (dataSource: DataSourceInstanceSettings) => boolean;
|
||||
onClear?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,7 +81,12 @@ export class DataSourcePicker extends PureComponent<DataSourcePickerProps, DataS
|
||||
}
|
||||
}
|
||||
|
||||
onChange = (item: SelectableValue<string>) => {
|
||||
onChange = (item: SelectableValue<string>, actionMeta: ActionMeta) => {
|
||||
if (actionMeta.action === 'clear' && this.props.onClear) {
|
||||
this.props.onClear();
|
||||
return;
|
||||
}
|
||||
|
||||
const dsSettings = this.dataSourceSrv.getInstanceSettings(item.value);
|
||||
|
||||
if (dsSettings) {
|
||||
@@ -142,11 +148,12 @@ export class DataSourcePicker extends PureComponent<DataSourcePickerProps, DataS
|
||||
}
|
||||
|
||||
render() {
|
||||
const { autoFocus, onBlur, openMenuOnFocus, placeholder, width } = this.props;
|
||||
const { autoFocus, onBlur, onClear, openMenuOnFocus, placeholder, width } = this.props;
|
||||
const { error } = this.state;
|
||||
const options = this.getDataSourceOptions();
|
||||
const value = this.getCurrentValue();
|
||||
const styles = getStyles();
|
||||
const isClearable = typeof onClear === 'function';
|
||||
|
||||
return (
|
||||
<div aria-label={selectors.components.DataSourcePicker.container}>
|
||||
@@ -156,7 +163,7 @@ export class DataSourcePicker extends PureComponent<DataSourcePickerProps, DataS
|
||||
menuShouldPortal
|
||||
className={styles.select}
|
||||
isMulti={false}
|
||||
isClearable={false}
|
||||
isClearable={isClearable}
|
||||
backspaceRemovesValue={false}
|
||||
onChange={this.onChange}
|
||||
options={options}
|
||||
|
@@ -0,0 +1,22 @@
|
||||
const ds1 = {
|
||||
id: 1,
|
||||
uid: 'c8eceabb-0275-4108-8f03-8f74faf4bf6d',
|
||||
type: 'prometheus',
|
||||
name: 'gdev-prometheus',
|
||||
meta: {
|
||||
info: {
|
||||
logos: {
|
||||
small: 'http://example.com/logo.png',
|
||||
},
|
||||
},
|
||||
},
|
||||
jsonData: {},
|
||||
access: 'proxy',
|
||||
};
|
||||
|
||||
export function getDataSourceSrv() {
|
||||
return {
|
||||
getList: () => [ds1],
|
||||
getInstanceSettings: () => ds1,
|
||||
};
|
||||
}
|
@@ -202,10 +202,10 @@ describe('SelectBase', () => {
|
||||
expect(selectEl).toBeInTheDocument();
|
||||
|
||||
await selectOptionInTest(selectEl, 'Option 2');
|
||||
expect(spy).toHaveBeenCalledWith({
|
||||
label: 'Option 2',
|
||||
value: 2,
|
||||
});
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
{ label: 'Option 2', value: 2 },
|
||||
{ action: 'select-option', name: undefined, option: undefined }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -20,7 +20,7 @@ import { MultiValueContainer, MultiValueRemove } from './MultiValue';
|
||||
import { useTheme2 } from '../../themes';
|
||||
import { getSelectStyles } from './getSelectStyles';
|
||||
import { cleanValue, findSelectedValue } from './utils';
|
||||
import { SelectBaseProps, SelectValue } from './types';
|
||||
import { ActionMeta, SelectBaseProps, SelectValue } from './types';
|
||||
import { deprecationWarning } from '@grafana/data';
|
||||
|
||||
interface ExtraValuesIndicatorProps {
|
||||
@@ -146,11 +146,11 @@ export function SelectBase<T>({
|
||||
const theme = useTheme2();
|
||||
const styles = getSelectStyles(theme);
|
||||
const onChangeWithEmpty = useCallback(
|
||||
(value: SelectValue<T>) => {
|
||||
(value: SelectValue<T>, action: ActionMeta) => {
|
||||
if (isMulti && (value === undefined || value === null)) {
|
||||
return onChange([]);
|
||||
return onChange([], action);
|
||||
}
|
||||
onChange(value);
|
||||
onChange(value, action);
|
||||
},
|
||||
[isMulti, onChange]
|
||||
);
|
||||
|
@@ -1,7 +1,9 @@
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import React from 'react';
|
||||
import { ActionMeta as SelectActionMeta } from 'react-select';
|
||||
|
||||
export type SelectValue<T> = T | SelectableValue<T> | T[] | Array<SelectableValue<T>>;
|
||||
export type ActionMeta = SelectActionMeta<{}>;
|
||||
export type InputActionMeta = {
|
||||
action: 'set-value' | 'input-change' | 'input-blur' | 'menu-close';
|
||||
};
|
||||
@@ -52,7 +54,7 @@ export interface SelectCommonProps<T> {
|
||||
/** The message to display when no options could be found */
|
||||
noOptionsMessage?: string;
|
||||
onBlur?: () => void;
|
||||
onChange: (value: SelectableValue<T>) => {} | void;
|
||||
onChange: (value: SelectableValue<T>, actionMeta: ActionMeta) => {} | void;
|
||||
onCloseMenu?: () => void;
|
||||
/** allowCustomValue must be enabled. Function decides what to do with that custom value. */
|
||||
onCreateOption?: (value: string) => void;
|
||||
|
@@ -4,3 +4,4 @@ export * from './completion';
|
||||
export * from './storybook';
|
||||
export * from './forms';
|
||||
export * from './icon';
|
||||
export * from './select';
|
||||
|
1
packages/grafana-ui/src/types/select.ts
Normal file
1
packages/grafana-ui/src/types/select.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { ActionMeta } from '../components/Select/types';
|
Reference in New Issue
Block a user