mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[ML] Replace EuiComboBox with EuiSuperSelect in Anomalies Table severity control (#24272)
* EuiSuperSelect replaces EuiComboBox in severity control * Add tests for selectSeverity component
This commit is contained in:
parent
6b5b4cc33b
commit
4a45224d6a
2 changed files with 134 additions and 49 deletions
|
@ -11,34 +11,40 @@
|
|||
*/
|
||||
import PropTypes from 'prop-types';
|
||||
import _ from 'lodash';
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
|
||||
import {
|
||||
EuiComboBox,
|
||||
EuiHighlight,
|
||||
EuiHealth,
|
||||
EuiSpacer,
|
||||
EuiSuperSelect,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import './styles/main.less';
|
||||
|
||||
import { getSeverityColor } from 'plugins/ml/../common/util/anomaly_utils';
|
||||
import { getSeverityColor } from '../../../../common/util/anomaly_utils';
|
||||
|
||||
const OPTIONS = [
|
||||
{ value: 0, label: 'warning', color: getSeverityColor(0) },
|
||||
{ value: 25, label: 'minor', color: getSeverityColor(25) },
|
||||
{ value: 50, label: 'major', color: getSeverityColor(50) },
|
||||
{ value: 75, label: 'critical', color: getSeverityColor(75) }
|
||||
{ val: 0, display: 'warning', color: getSeverityColor(0) },
|
||||
{ val: 25, display: 'minor', color: getSeverityColor(25) },
|
||||
{ val: 50, display: 'major', color: getSeverityColor(50) },
|
||||
{ val: 75, display: 'critical', color: getSeverityColor(75) },
|
||||
];
|
||||
|
||||
const optionsMap = {
|
||||
'warning': 0,
|
||||
'minor': 25,
|
||||
'major': 50,
|
||||
'critical': 75,
|
||||
};
|
||||
|
||||
function optionValueToThreshold(value) {
|
||||
// Builds the corresponding threshold object with the required display and val properties
|
||||
// from the specified value.
|
||||
const option = OPTIONS.find(opt => (opt.value === value));
|
||||
// Get corresponding threshold object with required display and val properties from the specified value.
|
||||
let threshold = OPTIONS.find(opt => (opt.val === value));
|
||||
|
||||
// Default to warning if supplied value doesn't map to one of the options.
|
||||
let threshold = OPTIONS[0];
|
||||
if (option !== undefined) {
|
||||
threshold = { display: option.label, val: option.value };
|
||||
if (threshold === undefined) {
|
||||
threshold = OPTIONS[0];
|
||||
}
|
||||
|
||||
return threshold;
|
||||
|
@ -53,59 +59,61 @@ class SelectSeverity extends Component {
|
|||
const thresholdState = this.mlSelectSeverityService.state.get('threshold');
|
||||
const thresholdValue = _.get(thresholdState, 'val', 0);
|
||||
const threshold = optionValueToThreshold(thresholdValue);
|
||||
const selectedOption = OPTIONS.find(opt => (opt.value === threshold.val));
|
||||
|
||||
// set initial selected option equal to threshold value
|
||||
const selectedOption = OPTIONS.find(opt => (opt.val === threshold.val));
|
||||
this.mlSelectSeverityService.state.set('threshold', threshold);
|
||||
|
||||
this.state = {
|
||||
selectedOptions: [selectedOption]
|
||||
valueDisplay: selectedOption.display,
|
||||
};
|
||||
}
|
||||
|
||||
onChange = (selectedOptions) => {
|
||||
if (selectedOptions.length === 0) {
|
||||
// Don't allow no options to be selected.
|
||||
return;
|
||||
}
|
||||
|
||||
onChange = (valueDisplay) => {
|
||||
this.setState({
|
||||
selectedOptions,
|
||||
valueDisplay: valueDisplay,
|
||||
});
|
||||
|
||||
const threshold = optionValueToThreshold(selectedOptions[0].value);
|
||||
const threshold = optionValueToThreshold(optionsMap[valueDisplay]);
|
||||
this.mlSelectSeverityService.state.set('threshold', threshold).changed();
|
||||
};
|
||||
}
|
||||
|
||||
renderOption = (option, searchValue, contentClassName) => {
|
||||
const { color, label, value } = option;
|
||||
return (
|
||||
<EuiHealth color={color}>
|
||||
<span className={contentClassName}>
|
||||
<EuiHighlight search={searchValue}>
|
||||
{label}
|
||||
</EuiHighlight>
|
||||
|
||||
<span>({value})</span>
|
||||
</span>
|
||||
</EuiHealth>
|
||||
);
|
||||
};
|
||||
getOptions = () =>
|
||||
OPTIONS.map(({ color, display, val }) => ({
|
||||
value: display,
|
||||
inputDisplay: (
|
||||
<Fragment>
|
||||
<EuiHealth color={color} style={{ lineHeight: 'inherit' }}>
|
||||
{display}
|
||||
</EuiHealth>
|
||||
</Fragment>
|
||||
),
|
||||
dropdownDisplay: (
|
||||
<Fragment>
|
||||
<EuiHealth color={color} style={{ lineHeight: 'inherit' }}>
|
||||
{display}
|
||||
</EuiHealth>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiText size="xs" color="subdued">
|
||||
<p className="euiTextColor--subdued">{`score ${val} and above`}</p>
|
||||
</EuiText>
|
||||
</Fragment>
|
||||
),
|
||||
}));
|
||||
|
||||
render() {
|
||||
const { selectedOptions } = this.state;
|
||||
const { valueDisplay } = this.state;
|
||||
const options = this.getOptions();
|
||||
|
||||
return (
|
||||
<EuiComboBox
|
||||
placeholder="Select severity"
|
||||
className="ml-select-severity"
|
||||
singleSelection={true}
|
||||
options={OPTIONS}
|
||||
selectedOptions={selectedOptions}
|
||||
<EuiSuperSelect
|
||||
hasDividers
|
||||
options={options}
|
||||
valueOfSelected={valueDisplay}
|
||||
onChange={this.onChange}
|
||||
renderOption={this.renderOption}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SelectSeverity.propTypes = {
|
||||
mlSelectSeverityService: PropTypes.object.isRequired,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { SelectSeverity } from './select_severity';
|
||||
|
||||
|
||||
const severityService = {
|
||||
state: {
|
||||
'threshold': { color: '#d2e9f7', display: 'warning', val: 0 },
|
||||
get: () => ({ color: '#d2e9f7', display: 'warning', val: 0 }),
|
||||
set: () => ({
|
||||
changed: () => {}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
describe('SelectSeverity', () => {
|
||||
|
||||
test('creates correct severity options and initial selected value', () => {
|
||||
const wrapper = shallow(<SelectSeverity mlSelectSeverityService={severityService}/>);
|
||||
const options = wrapper.props().options;
|
||||
const defaultSelectedValue = wrapper.props().valueOfSelected;
|
||||
|
||||
expect(defaultSelectedValue).toBe('warning');
|
||||
expect(options.length).toEqual(4);
|
||||
|
||||
// excpect options Array to equal Array containing Object that contains the property
|
||||
expect(options).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
value: 'warning'
|
||||
})
|
||||
])
|
||||
);
|
||||
|
||||
expect(options).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
value: 'minor'
|
||||
})
|
||||
])
|
||||
);
|
||||
|
||||
expect(options).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
value: 'major'
|
||||
})
|
||||
])
|
||||
);
|
||||
|
||||
expect(options).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
value: 'critical'
|
||||
})
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
test('state for currently selected value is updated correctly on click', () => {
|
||||
const wrapper = shallow(<SelectSeverity mlSelectSeverityService={severityService} />);
|
||||
|
||||
const defaultSelectedValue = wrapper.props().valueOfSelected;
|
||||
expect(defaultSelectedValue).toBe('warning');
|
||||
|
||||
wrapper.simulate('change', 'critical');
|
||||
const updatedSelectedValue = wrapper.props().valueOfSelected;
|
||||
expect(updatedSelectedValue).toBe('critical');
|
||||
});
|
||||
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue