[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:
Melissa Alvarez 2018-10-23 13:35:42 +01:00 committed by GitHub
parent 6b5b4cc33b
commit 4a45224d6a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 134 additions and 49 deletions

View file

@ -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>
&nbsp;
<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,
};

View file

@ -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');
});
});