Remove react-select from kibana (#18876)

* remove react-select from AggSelect

* update field_select to use EuiComboBox

* metric_select

* moving_average

* percentile

* series_agg

* std_deviation

* removing some more react-select instances

* icon_select and group_by_select

* gauge type

* markdown

* set isClearable prop

* remove react-select from timeseries config

* remove react-select from timeseries panel options

* remove react select from terms

* remove react-select from table config

* remove react-select from data_format_picker

* fix create_select_handler mocha test

* remove react-select from kibana

* update tsvb functional tests

* set isDisabled prop on EuiComboBox where disabld prop was set for Select

* use durationOutputOptions for duration 'to' options
This commit is contained in:
Nathan Reese 2018-05-30 09:21:38 -06:00 committed by GitHub
parent 751b0c173d
commit 8de20f23fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 387 additions and 828 deletions

View file

@ -178,7 +178,6 @@
"react-markdown": "^3.1.4",
"react-redux": "^5.0.6",
"react-router-dom": "4.2.2",
"react-select": "^1.2.0",
"react-sizeme": "^2.3.6",
"react-toggle": "4.0.2",
"reactcss": "1.2.3",

View file

@ -247,7 +247,6 @@ dashboard-viewport-provider {
/**
* 1. Fix Firefox bug where a value of overflow: hidden will prevent scrolling in a panel where the spy panel does
* not have enough room.
* 2. react-select used in input control vis needs `visible` overflow to avoid clipping selection list
*/
.dashboard-panel {
z-index: auto;
@ -259,7 +258,7 @@ dashboard-viewport-provider {
background: @dashboard-panel-bg;
color: @dashboard-panel-color;
padding: 0;
overflow: visible; /* 1, 2 */
overflow: visible; /* 1 */
position: relative;

View file

@ -18,8 +18,10 @@
*/
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Select from 'react-select';
import React from 'react';
import {
EuiComboBox,
} from '@elastic/eui';
const metricAggs = [
{ label: 'Average', value: 'avg' },
@ -63,89 +65,12 @@ const specialAggs = [
{ label: 'Math', value: 'math' },
];
class AggSelectOption extends Component {
constructor(props) {
super(props);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.handleMouseEnter = this.handleMouseEnter.bind(this);
this.handleMouseDown = this.handleMouseDown.bind(this);
}
handleMouseDown(event) {
event.preventDefault();
event.stopPropagation();
this.props.onSelect(this.props.option, event);
}
handleMouseEnter(event) {
this.props.onFocus(this.props.option, event);
}
handleMouseMove(event) {
if (this.props.isFocused) return;
this.props.onFocus(this.props.option, event);
}
render() {
const { label, heading, pipeline } = this.props.option;
const style = {
paddingLeft: heading ? 0 : 10,
};
// We can ignore that the <div> does not have keyboard handlers even though
// it has mouse handlers, since react-select still takes care, that this works
// well with keyboard.
/* eslint-disable jsx-a11y/no-static-element-interactions */
if (heading) {
let note;
if (pipeline) {
note = (
<span className="vis_editor__agg_select-note">
(requires child aggregation)
</span>
);
}
return (
<div
className="Select-option vis_editor__agg_select-heading"
onMouseEnter={this.handleMouseEnter}
onMouseDown={this.handleMouseDown}
onMouseMove={this.handleMouseMove}
aria-label={label}
>
<span className="Select-value-label" style={style}>
<strong>{label}</strong>
{note}
</span>
</div>
);
}
return (
<div
className={this.props.className}
onMouseEnter={this.handleMouseEnter}
onMouseDown={this.handleMouseDown}
onMouseMove={this.handleMouseMove}
aria-label={label}
>
<span className="Select-value-label" style={style}>
{this.props.children}
</span>
</div>
);
/* eslint-enable jsx-a11y/no-static-element-interactions */
}
}
AggSelectOption.props = {
children: PropTypes.node,
className: PropTypes.string,
isDisabled: PropTypes.bool,
isFocused: PropTypes.bool,
isSelected: PropTypes.bool,
onFocus: PropTypes.func,
onSelect: PropTypes.func,
option: PropTypes.object.isRequired,
};
const allAggOptions = [
...metricAggs,
...pipelineAggs,
...siblingAggs,
...specialAggs
];
function filterByPanelType(panelType) {
return agg => {
@ -155,7 +80,12 @@ function filterByPanelType(panelType) {
}
function AggSelect(props) {
const { siblings, panelType } = props;
const { siblings, panelType, value } = props;
const selectedOption = allAggOptions.find(option => {
return value === option.value;
});
const selectedOptions = selectedOption ? [selectedOption] : [];
let enablePipelines = siblings.some(
s => !!metricAggs.find(m => m.value === s.type)
@ -169,55 +99,39 @@ function AggSelect(props) {
options = [
{
label: 'Metric Aggregations',
value: null,
heading: true,
disabled: true,
options: metricAggs,
},
...metricAggs,
{
label: 'Parent Pipeline Aggregations',
value: null,
pipeline: true,
heading: true,
disabled: true,
options: pipelineAggs
.filter(filterByPanelType(panelType))
.map(agg => ({ ...agg, disabled: !enablePipelines }))
},
...pipelineAggs
.filter(filterByPanelType(panelType))
.map(agg => ({ ...agg, disabled: !enablePipelines })),
{
label: 'Sibling Pipeline Aggregations',
value: null,
pipeline: true,
heading: true,
disabled: true,
options: siblingAggs.map(agg => ({ ...agg, disabled: !enablePipelines })),
},
...siblingAggs.map(agg => ({ ...agg, disabled: !enablePipelines })),
{
label: 'Special Aggregations',
value: null,
pipeline: true,
heading: true,
disabled: true,
options: specialAggs.map(agg => ({ ...agg, disabled: !enablePipelines })),
},
...specialAggs.map(agg => ({ ...agg, disabled: !enablePipelines })),
];
}
const handleChange = value => {
if (!value) return;
if (value.disabled) return;
if (value.value) props.onChange(value);
const handleChange = selectedOptions => {
if (!selectedOptions || selectedOptions.length <= 0) return;
props.onChange(selectedOptions);
};
return (
<div data-test-subj="aggSelector" className="vis_editor__row_item">
<Select
aria-label="Select aggregation"
clearable={false}
<EuiComboBox
isClearable={false}
placeholder="Select aggregation"
options={options}
value={props.value}
optionComponent={AggSelectOption}
selectedOptions={selectedOptions}
onChange={handleChange}
singleSelection={true}
/>
</div>
);

View file

@ -19,11 +19,13 @@
import PropTypes from 'prop-types';
import React from 'react';
import Select from 'react-select';
import {
EuiComboBox,
} from '@elastic/eui';
import generateByTypeFilter from '../lib/generate_by_type_filter';
function FieldSelect(props) {
const { type, fields, indexPattern } = props;
const { type, fields, indexPattern, value, onChange, disabled } = props;
if (type === 'count') {
return null;
}
@ -33,14 +35,19 @@ function FieldSelect(props) {
return { label: field.name, value: field.name };
});
const selectedOption = options.find(option => {
return value === option.value;
});
const selectedOptions = selectedOption ? [selectedOption] : [];
return (
<Select
inputProps={{ id: props.id }}
<EuiComboBox
placeholder="Select field..."
disabled={props.disabled}
isDisabled={disabled}
options={options}
value={props.value}
onChange={props.onChange}
selectedOptions={selectedOptions}
onChange={onChange}
singleSelection={true}
/>
);
}

View file

@ -20,7 +20,9 @@
import PropTypes from 'prop-types';
import React from 'react';
import _ from 'lodash';
import Select from 'react-select';
import {
EuiComboBox,
} from '@elastic/eui';
import calculateSiblings from '../lib/calculate_siblings';
import calculateLabel from '../../../common/calculate_label';
import basicAggs from '../../../common/basic_aggs';
@ -86,14 +88,20 @@ function MetricSelect(props) {
const label = calculateLabel(row, metrics);
return { value: row.id, label };
});
const allOptions = [...options, ...props.additionalOptions, ...percentileOptions];
const selectedOption = allOptions.find(option => {
return value === option.value;
});
const selectedOptions = selectedOption ? [selectedOption] : [];
return (
<Select
aria-label="Select metric"
<EuiComboBox
placeholder="Select metric..."
options={[...options, ...props.additionalOptions, ...percentileOptions]}
value={value}
options={allOptions}
selectedOptions={selectedOptions}
onChange={onChange}
singleSelection={true}
/>
);
}

View file

@ -22,12 +22,14 @@ import React from 'react';
import AggRow from './agg_row';
import AggSelect from './agg_select';
import MetricSelect from './metric_select';
import Select from 'react-select';
import createChangeHandler from '../lib/create_change_handler';
import createSelectHandler from '../lib/create_select_handler';
import createTextHandler from '../lib/create_text_handler';
import createNumberHandler from '../lib/create_number_handler';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
export const MovingAverageAgg = props => {
const { siblings } = props;
@ -54,6 +56,13 @@ export const MovingAverageAgg = props => {
{ label: 'False', value: 0 }
];
const htmlId = htmlIdGenerator();
const selectedModelOption = modelOptions.find(option => {
return model.model === option.value;
});
const selectedMinimizeOption = minimizeOptions.find(option => {
return model.minimize === option.value;
});
return (
<AggRow
disableDelete={props.disableDelete}
@ -86,13 +95,14 @@ export const MovingAverageAgg = props => {
<div className="vis_editor__agg_row-item">
<div className="vis_editor__row_item">
<label className="vis_editor__label" htmlFor={htmlId('model')}>Model</label>
<Select
inputProps={{ id: htmlId('model') }}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('model')}
placeholder="Select..."
onChange={handleSelectChange('model')}
value={props.model.model}
options={modelOptions}
selectedOptions={selectedModelOption ? [selectedModelOption] : []}
onChange={handleSelectChange('model')}
singleSelection={true}
/>
</div>
<div className="vis_editor__row_item">
@ -109,12 +119,13 @@ export const MovingAverageAgg = props => {
</div>
<div className="vis_editor__row_item">
<label className="vis_editor__label" htmlFor={htmlId('minimize')}>Minimize</label>
<Select
inputProps={{ id: htmlId('minimize') }}
<EuiComboBox
id={htmlId('minimize')}
placeholder="Select..."
onChange={handleSelectChange('minimize')}
value={model.minimize}
options={minimizeOptions}
selectedOptions={selectedMinimizeOption ? [selectedMinimizeOption] : []}
onChange={handleSelectChange('minimize')}
singleSelection={true}
/>
</div>
<div className="vis_editor__row_item">

View file

@ -25,11 +25,13 @@ import FieldSelect from './field_select';
import AggRow from './agg_row';
import * as collectionActions from '../lib/collection_actions';
import AddDeleteButtons from '../add_delete_buttons';
import Select from 'react-select';
import uuid from 'uuid';
import createChangeHandler from '../lib/create_change_handler';
import createSelectHandler from '../lib/create_select_handler';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
const newPercentile = (opts) => {
return _.assign({ id: uuid.v1(), mode: 'line', shade: 0.2 }, opts);
};
@ -45,7 +47,7 @@ class Percentiles extends Component {
return (e) => {
const handleChange = collectionActions.handleChange.bind(null, this.props);
const part = {};
part[name] = _.get(e, 'value', _.get(e, 'target.value'));
part[name] = _.get(e, '[0].value', _.get(e, 'target.value'));
handleChange(_.assign({}, item, part));
};
}
@ -64,6 +66,9 @@ class Percentiles extends Component {
optionsStyle.display = 'none';
}
const htmlId = htmlIdGenerator(model.id);
const selectedModeOption = modeOptions.find(option => {
return model.mode === option.value;
});
return (
<div className="vis_editor__percentiles-row" key={model.id}>
<div className="vis_editor__percentiles-content">
@ -78,12 +83,13 @@ class Percentiles extends Component {
/>
<label className="vis_editor__label" htmlFor={htmlId('mode')}>Mode</label>
<div className="vis_editor__row_item">
<Select
inputProps={{ id: htmlId('mode') }}
clearable={false}
onChange={this.handleTextChange(model, 'mode')}
<EuiComboBox
isClearable={false}
id={htmlId('mode')}
options={modeOptions}
value={model.mode}
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
onChange={this.handleTextChange(model, 'mode')}
singleSelection={true}
/>
</div>
<label style={optionsStyle} className="vis_editor__label" htmlFor={htmlId('fillTo')}>

View file

@ -20,11 +20,13 @@
import PropTypes from 'prop-types';
import React from 'react';
import AggSelect from './agg_select';
import Select from 'react-select';
import AggRow from './agg_row';
import createChangeHandler from '../lib/create_change_handler';
import createSelectHandler from '../lib/create_select_handler';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
function SeriesAgg(props) {
const { panel, model } = props;
@ -45,6 +47,9 @@ function SeriesAgg(props) {
{ label: 'Overall Avg', value: 'overall_avg' },
{ label: 'Cumlative Sum', value: 'cumlative_sum' },
];
const selectedFunctionOption = functionOptions.find(option => {
return model.function === option.value;
});
if (panel.type === 'table') {
return (
@ -83,11 +88,12 @@ function SeriesAgg(props) {
</div>
<div className="vis_editor__item">
<label className="vis_editor__label" htmlFor={htmlId('function')}>Function</label>
<Select
inputProps={{ id: htmlId('function') }}
value={model.function}
<EuiComboBox
id={htmlId('function')}
options={functionOptions}
selectedOptions={selectedFunctionOption ? [selectedFunctionOption] : []}
onChange={handleSelectChange('function')}
singleSelection={true}
/>
</div>
</AggRow>

View file

@ -22,11 +22,13 @@ import React from 'react';
import AggSelect from './agg_select';
import FieldSelect from './field_select';
import AggRow from './agg_row';
import Select from 'react-select';
import createChangeHandler from '../lib/create_change_handler';
import createSelectHandler from '../lib/create_select_handler';
import createTextHandler from '../lib/create_text_handler';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
export const StandardDeviationAgg = props => {
const { series, panel, fields } = props;
@ -49,6 +51,9 @@ export const StandardDeviationAgg = props => {
const indexPattern = series.override_index_pattern && series.series_index_pattern || panel.index_pattern;
const htmlId = htmlIdGenerator();
const selectedModeOption = modeOptions.find(option => {
return model.mode === option.value;
});
return (
<AggRow
@ -90,11 +95,12 @@ export const StandardDeviationAgg = props => {
</div>
<div className="vis_editor__row_item">
<label className="vis_editor__label" htmlFor={htmlId('mode')}>Mode</label>
<Select
inputProps={{ id: htmlId('mode') }}
<EuiComboBox
id={htmlId('mode')}
options={modeOptions}
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
onChange={handleSelectChange('mode')}
value={model.mode}
singleSelection={true}
/>
</div>
</AggRow>

View file

@ -22,11 +22,13 @@ import React from 'react';
import AggRow from './agg_row';
import MetricSelect from './metric_select';
import AggSelect from './agg_select';
import Select from 'react-select';
import createChangeHandler from '../lib/create_change_handler';
import createSelectHandler from '../lib/create_select_handler';
import createTextHandler from '../lib/create_text_handler';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
export const StandardSiblingAgg = props => {
const { siblings } = props;
@ -58,15 +60,19 @@ export const StandardSiblingAgg = props => {
{ label: 'Lower Bound', value: 'lower' },
{ label: 'Bounds Band', value: 'band' }
];
const selectedModeOption = modeOptions.find(option => {
return model.mode === option.value;
});
stdDev.mode = (
<div className="vis_editor__row_item">
<label className="vis_editor__label" htmlFor={htmlId('mode')}>Mode</label>
<Select
inputProps={{ id: htmlId('mode') }}
<EuiComboBox
id={htmlId('mode')}
options={modeOptions}
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
onChange={handleSelectChange('mode')}
value={model.mode}
singleSelection={true}
/>
</div>
);

View file

@ -21,11 +21,13 @@ import React from 'react';
import AggRow from './agg_row';
import AggSelect from './agg_select';
import FieldSelect from './field_select';
import Select from 'react-select';
import createChangeHandler from '../lib/create_change_handler';
import createSelectHandler from '../lib/create_select_handler';
import createTextHandler from '../lib/create_text_handler';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
export const TopHitAgg = props => {
const { fields, series, panel } = props;
@ -56,6 +58,12 @@ export const TopHitAgg = props => {
];
const htmlId = htmlIdGenerator();
const selectedAggWithOption = aggWithOptions.find(option => {
return model.agg_with === option.value;
});
const selectedOrderOption = orderOptions.find(option => {
return model.order === option.value;
});
return (
<AggRow
disableDelete={props.disableDelete}
@ -106,13 +114,14 @@ export const TopHitAgg = props => {
<label className="vis_editor__label" htmlFor={htmlId('agg_with')}>
Aggregate with
</label>
<Select
inputProps={{ id: htmlId('agg_with') }}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('agg_with')}
placeholder="Select..."
onChange={handleSelectChange('agg_with')}
value={model.agg_with}
options={aggWithOptions}
selectedOptions={selectedAggWithOption ? [selectedAggWithOption] : []}
onChange={handleSelectChange('agg_with')}
singleSelection={true}
/>
</div>
<div className="vis_editor__row_item">
@ -132,13 +141,14 @@ export const TopHitAgg = props => {
<label className="vis_editor__label" htmlFor={htmlId('order')}>
Order
</label>
<Select
inputProps={{ id: htmlId('order') }}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('order')}
placeholder="Select..."
onChange={handleSelectChange('order')}
value={model.order}
options={orderOptions}
selectedOptions={selectedOrderOption ? [selectedOrderOption] : []}
onChange={handleSelectChange('order')}
singleSelection={true}
/>
</div>
</div>

View file

@ -35,7 +35,7 @@ class CalculationVars extends Component {
return (e) => {
const handleChange = collectionActions.handleChange.bind(null, this.props);
const part = {};
part[name] = _.get(e, 'value', _.get(e, 'target.value'));
part[name] = _.get(e, '[0].value', _.get(e, 'target.value'));
handleChange(_.assign({}, item, part));
};
}

View file

@ -56,7 +56,7 @@ class AnnotationsEditor extends Component {
return (e) => {
const handleChange = collectionActions.handleChange.bind(null, this.props);
const part = {};
part[name] = _.get(e, 'value', _.get(e, 'target.value'));
part[name] = _.get(e, '[0].value', _.get(e, 'target.value'));
handleChange(_.assign({}, item, part));
};
}

View file

@ -21,10 +21,12 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import _ from 'lodash';
import AddDeleteButtons from './add_delete_buttons';
import Select from 'react-select';
import * as collectionActions from './lib/collection_actions';
import ColorPicker from './color_picker';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
class ColorRules extends Component {
@ -37,7 +39,7 @@ class ColorRules extends Component {
return (e) => {
const handleChange = collectionActions.handleChange.bind(null, this.props);
const part = {};
part[name] = cast(_.get(e, 'value', _.get(e, 'target.value')));
part[name] = cast(_.get(e, '[0].value', _.get(e, 'target.value')));
if (part[name] === 'undefined') part[name] = undefined;
if (part[name] === NaN) part[name] = undefined;
handleChange(_.assign({}, item, part));
@ -60,6 +62,10 @@ class ColorRules extends Component {
handleChange(_.assign({}, model, part));
};
const htmlId = htmlIdGenerator(model.id);
const selectedOperatorOption = operatorOptions.find(option => {
return model.opperator === option.value;
});
let secondary;
if (!this.props.hideSecondary) {
secondary = (
@ -86,11 +92,12 @@ class ColorRules extends Component {
if metric is
</label>
<div className="color_rules__item">
<Select
inputProps={{ id: htmlId('ifMetricIs') }}
onChange={this.handleChange(model, 'opperator')}
value={model.opperator}
<EuiComboBox
id={htmlId('ifMetricIs')}
options={operatorOptions}
selectedOptions={selectedOperatorOption ? [selectedOperatorOption] : []}
onChange={this.handleChange(model, 'opperator')}
singleSelection={true}
/>
</div>
<input

View file

@ -20,7 +20,9 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import _ from 'lodash';
import Select from 'react-select';
import {
EuiComboBox,
} from '@elastic/eui';
import { durationOutputOptions, durationInputOptions } from './lib/durations';
const durationFormatTest = /[pnumshdwMY]+,[pnumshdwMY]+/;
@ -44,34 +46,46 @@ class DataFormatPicker extends Component {
}
handleCustomChange() {
this.props.onChange({ value: this.custom && this.custom.value || '' });
this.props.onChange([{ value: this.custom && this.custom.value || '' }]);
}
handleChange(value) {
if (value.value === 'custom') {
handleChange(selectedOptions) {
if (selectedOptions.length < 1) {
return;
}
if (selectedOptions[0].value === 'custom') {
this.handleCustomChange();
} else if (value.value === 'duration') {
} else if (selectedOptions[0].value === 'duration') {
const { from, to, decimals } = this.state;
this.props.onChange({
this.props.onChange([{
value: `${from},${to},${decimals}`
});
}]);
} else {
this.props.onChange(value);
this.props.onChange(selectedOptions);
}
}
handleDurationChange(name) {
return (value) => {
if (name === 'decimals') {
value = this.decimals;
return (selectedOptions) => {
if (selectedOptions.length < 1) {
return;
}
let newValue;
if (name === 'decimals') {
newValue = this.decimals.value;
} else {
newValue = selectedOptions[0].value;
}
this.setState({
[name]: value.value
[name]: newValue
}, () => {
const { from, to, decimals } = this.state;
this.props.onChange({
this.props.onChange([{
value: `${from},${to},${decimals}`
});
}]);
});
};
}
@ -92,39 +106,51 @@ class DataFormatPicker extends Component {
{ label: 'Duration', value: 'duration' },
{ label: 'Custom', value: 'custom' }
];
const selectedOption = options.find(option => {
return defaultValue === option.value;
});
let custom;
if (defaultValue === 'duration') {
const [from, to, decimals] = value.split(',');
const selectedFrom = durationInputOptions.find(option => {
return from === option.value;
});
const selectedTo = durationOutputOptions.find(option => {
return to === option.value;
});
return (
<div className="vis_editor__data_format_picker-container">
<div className="vis_editor__label">
{this.props.label}
</div>
<div className="vis_editor__item">
<Select
clearable={false}
value={defaultValue}
<EuiComboBox
isClearable={false}
options={options}
selectedOptions={selectedOption ? [selectedOption] : []}
onChange={this.handleChange}
singleSelection={true}
/>
</div>
<div className="vis_editor__label">From</div>
<div className="vis_editor__item">
<Select
clearable={false}
value={from}
<EuiComboBox
isClearable={false}
options={durationInputOptions}
selectedOptions={selectedFrom ? [selectedFrom] : []}
onChange={this.handleDurationChange('from')}
singleSelection={true}
/>
</div>
<div className="vis_editor__label">To</div>
<div className="vis_editor__item">
<Select
clearable={false}
value={to}
<EuiComboBox
isClearable={false}
options={durationOutputOptions}
selectedOptions={selectedTo ? [selectedTo] : []}
onChange={this.handleDurationChange('to')}
singleSelection={true}
/>
</div>
<div className="vis_editor__label">Decimal Places</div>
@ -162,11 +188,12 @@ class DataFormatPicker extends Component {
{this.props.label}
</div>
<div className="vis_editor__item">
<Select
clearable={false}
value={defaultValue}
<EuiComboBox
isClearable={false}
options={options}
selectedOptions={selectedOption ? [selectedOption] : []}
onChange={this.handleChange}
singleSelection={true}
/>
</div>
{custom}

View file

@ -18,79 +18,14 @@
*/
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Select from 'react-select';
import React from 'react';
import {
EuiComboBox,
} from '@elastic/eui';
class IconOption extends Component {
constructor(props) {
super(props);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.handleMouseEnter = this.handleMouseEnter.bind(this);
this.handleMouseDown = this.handleMouseDown.bind(this);
}
handleMouseDown(event) {
event.preventDefault();
event.stopPropagation();
this.props.onSelect(this.props.option, event);
}
handleMouseEnter(event) {
this.props.onFocus(this.props.option, event);
}
handleMouseMove(event) {
if (this.props.isFocused) return;
this.props.onFocus(this.props.option, event);
}
render() {
const icon = this.props.option.value;
const label = this.props.option.label;
// We can ignore that the <div> does not have keyboard handlers even though
// it has mouse handlers, since react-select still takes care, that this works
// well with keyboard.
/* eslint-disable jsx-a11y/no-static-element-interactions */
return (
<div
className={this.props.className}
onMouseEnter={this.handleMouseEnter}
onMouseDown={this.handleMouseDown}
onMouseMove={this.handleMouseMove}
>
<span
className="Select-value-label"
aria-label={`${label} icon`}
>
<span
className={`vis_editor__icon_select-option kuiIcon ${icon}`}
aria-hidden="true"
/>
{ this.props.children }
</span>
</div>
);
/* eslint-enable jsx-a11y/no-static-element-interactions */
}
}
IconOption.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
isDisabled: PropTypes.bool,
isFocused: PropTypes.bool,
isSelected: PropTypes.bool,
onFocus: PropTypes.func,
onSelect: PropTypes.func,
option: PropTypes.object.isRequired,
};
function IconValue(props) {
const icon = props.value && props.value.value;
const label = props.value && props.value.label;
function renderOption(option) {
const icon = option.value;
const label = option.label;
return (
<div className="Select-value">
<span
@ -98,28 +33,25 @@ function IconValue(props) {
aria-label={`${label} icon`}
>
<span className={`vis_editor__icon_select-value kuiIcon ${icon}`} />
{ props.children }
{ label }
</span>
</div>
);
}
IconValue.propTypes = {
children: PropTypes.node,
placeholder: PropTypes.string,
value: PropTypes.object.isRequired
};
function IconSelect(props) {
const selectedIcon = props.icons.find(option => {
return props.value === option.value;
});
return (
<Select
inputProps={{ id: props.id }}
clearable={false}
onChange={props.onChange}
value={props.value}
optionComponent={IconOption}
valueComponent={IconValue}
<EuiComboBox
isClearable={false}
id={props.id}
options={props.icons}
selectedOptions={selectedIcon ? [selectedIcon] : []}
onChange={props.onChange}
singleSelection={true}
renderOption={renderOption}
/>
);
}

View file

@ -29,7 +29,7 @@ describe('createSelectHandler()', () => {
handleChange = sinon.spy();
changeHandler = createSelectHandler(handleChange);
const fn = changeHandler('test');
fn({ value: 'foo' });
fn([{ value: 'foo' }]);
});
it('calls handleChange() funciton with partial', () => {

View file

@ -19,10 +19,10 @@
import _ from 'lodash';
export default (handleChange) => {
return (name) => (value) => {
return (name) => (selectedOptions) => {
if (_.isFunction(handleChange)) {
return handleChange({
[name]: value && value.value || null
[name]: _.get(selectedOptions, '[0].value', null)
});
}
};

View file

@ -21,14 +21,16 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import SeriesEditor from '../series_editor';
import { IndexPattern } from '../index_pattern';
import Select from 'react-select';
import createSelectHandler from '../lib/create_select_handler';
import createTextHandler from '../lib/create_text_handler';
import ColorRules from '../color_rules';
import ColorPicker from '../color_picker';
import uuid from 'uuid';
import YesNo from '../yes_no';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
class GaugePanelConfig extends Component {
@ -71,6 +73,9 @@ class GaugePanelConfig extends Component {
{ label: 'Half Circle', value: 'half' }
];
const htmlId = htmlIdGenerator();
const selectedGaugeStyleOption = styleOptions.find(option => {
return model.gauge_style === option.value;
});
let view;
if (selectedTab === 'data') {
view = (
@ -129,13 +134,13 @@ class GaugePanelConfig extends Component {
<label className="vis_editor__label" htmlFor={htmlId('gaugeStyle')}>
Gauge Style
</label>
<Select
inputProps={{ id: htmlId('gaugeStyle') }}
autosize={false}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('gaugeStyle')}
options={styleOptions}
value={model.gauge_style}
selectedOptions={selectedGaugeStyleOption ? [selectedGaugeStyleOption] : []}
onChange={handleSelectChange('gauge_style')}
singleSelection={true}
/>
</div>

View file

@ -22,7 +22,6 @@ import React, { Component } from 'react';
import SeriesEditor from '../series_editor';
import { IndexPattern } from '../index_pattern';
import 'brace/mode/less';
import Select from 'react-select';
import createSelectHandler from '../lib/create_select_handler';
import createTextHandler from '../lib/create_text_handler';
import ColorPicker from '../color_picker';
@ -30,7 +29,10 @@ import YesNo from '../yes_no';
import MarkdownEditor from '../markdown_editor';
import less from 'less/lib/less-browser';
import { KuiCodeEditor } from '@kbn/ui-framework/components';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
const lessC = less(window, { env: 'production' });
class MarkdownPanelConfig extends Component {
@ -73,6 +75,9 @@ class MarkdownPanelConfig extends Component {
{ label: 'Middle', value: 'middle' },
{ label: 'Bottom', value: 'bottom' }
];
const selectedAlignOption = alignOptions.find(option => {
return model.markdown_vertical_align === option.value;
});
let view;
if (selectedTab === 'markdown') {
view = (<MarkdownEditor {...this.props}/>);
@ -129,13 +134,13 @@ class MarkdownPanelConfig extends Component {
Vertical Alignment
</label>
<div className="vis_editor__row_item">
<Select
inputProps={{ id: htmlId('valign') }}
autosize={true}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('valign')}
options={alignOptions}
value={model.markdown_vertical_align}
selectedOptions={selectedAlignOption ? [selectedAlignOption] : []}
onChange={handleSelectChange('markdown_vertical_align')}
singleSelection={true}
/>
</div>
</div>

View file

@ -22,12 +22,14 @@ import React, { Component } from 'react';
import SeriesEditor from '../series_editor';
import AnnotationsEditor from '../annotations_editor';
import { IndexPattern } from '../index_pattern';
import Select from 'react-select';
import createSelectHandler from '../lib/create_select_handler';
import createTextHandler from '../lib/create_text_handler';
import ColorPicker from '../color_picker';
import YesNo from '../yes_no';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
class TimeseriesPanelConfig extends Component {
@ -57,15 +59,25 @@ class TimeseriesPanelConfig extends Component {
{ label: 'Right', value: 'right' },
{ label: 'Left', value: 'left' }
];
const selectedPositionOption = positionOptions.find(option => {
return model.axis_position === option.value;
});
const scaleOptions = [
{ label: 'Normal', value: 'normal' },
{ label: 'Log', value: 'log' }
];
const selectedAxisScaleOption = scaleOptions.find(option => {
return model.axis_scale === option.value;
});
const legendPositionOptions = [
{ label: 'Right', value: 'right' },
{ label: 'Left', value: 'left' },
{ label: 'Bottom', value: 'bottom' }
];
const selectedLegendPosOption = legendPositionOptions.find(option => {
return model.legend_position === option.value;
});
let view;
if (selectedTab === 'data') {
view = (
@ -112,24 +124,24 @@ class TimeseriesPanelConfig extends Component {
/>
<label className="vis_editor__label" htmlFor={htmlId('axisPos')}>Axis Position</label>
<div className="vis_editor__row_item">
<Select
inputProps={{ id: htmlId('axisPos') }}
autosize={false}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('axisPos')}
options={positionOptions}
value={model.axis_position}
selectedOptions={selectedPositionOption ? [selectedPositionOption] : []}
onChange={handleSelectChange('axis_position')}
singleSelection={true}
/>
</div>
<label className="vis_editor__label" htmlFor={htmlId('axisPos')}>Axis Scale</label>
<div className="vis_editor__row_item">
<Select
inputProps={{ id: htmlId('axisScale') }}
autosize={false}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('axisScale')}
options={scaleOptions}
value={model.axis_scale}
selectedOptions={selectedAxisScaleOption ? [selectedAxisScaleOption] : []}
onChange={handleSelectChange('axis_scale')}
singleSelection={true}
/>
</div>
</div>
@ -148,12 +160,13 @@ class TimeseriesPanelConfig extends Component {
/>
<label className="vis_editor__label" htmlFor={htmlId('legendPos')}>Legend Position</label>
<div className="vis_editor__row_item">
<Select
inputProps={{ id: htmlId('legendPos') }}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('legendPos')}
options={legendPositionOptions}
value={model.legend_position}
selectedOptions={selectedLegendPosOption ? [selectedLegendPosOption] : []}
onChange={handleSelectChange('legend_position')}
singleSelection={true}
/>
</div>
<div className="vis_editor__label">Display Grid</div>

View file

@ -19,7 +19,9 @@
import PropTypes from 'prop-types';
import React from 'react';
import Select from 'react-select';
import {
EuiComboBox,
} from '@elastic/eui';
function GroupBySelect(props) {
const modeOptions = [
{ label: 'Everything', value: 'everything' },
@ -27,12 +29,17 @@ function GroupBySelect(props) {
{ label: 'Filters', value: 'filters' },
{ label: 'Terms', value: 'terms' }
];
const selectedValue = props.value || 'everything';
const selectedOption = modeOptions.find(option => {
return selectedValue === option.value;
});
return (
<Select
clearable={false}
value={props.value || 'everything'}
onChange={props.onChange}
<EuiComboBox
isClearable={false}
options={modeOptions}
selectedOptions={[selectedOption]}
onChange={props.onChange}
singleSelection={true}
/>
);

View file

@ -24,7 +24,9 @@ import createTextHandler from '../lib/create_text_handler';
import createSelectHandler from '../lib/create_select_handler';
import FieldSelect from '../aggs/field_select';
import MetricSelect from '../aggs/metric_select';
import Select from 'react-select';
import {
EuiComboBox,
} from '@elastic/eui';
export const SplitByTerms = props => {
const handleTextChange = createTextHandler(props.onChange);
@ -40,6 +42,9 @@ export const SplitByTerms = props => {
{ value: 'desc', label: 'Descending' },
{ value: 'asc', label: 'Ascending' },
];
const selectedDirectionOption = dirOptions.find(option => {
return model.terms_direction === option.value;
});
return (
<div className="vis_editor__split-container">
@ -80,11 +85,12 @@ export const SplitByTerms = props => {
</div>
<div className="vis_editor__label">Direction</div>
<div className="vis_editor__split-aggs">
<Select
<EuiComboBox
isClearable={false}
options={dirOptions}
clearable={false}
value={model.terms_direction}
selectedOptions={selectedDirectionOption ? [selectedDirectionOption] : []}
onChange={handleSelectChange('terms_direction')}
singleSelection={true}
/>
</div>
</div>

View file

@ -24,10 +24,12 @@ import DataFormatPicker from '../../data_format_picker';
import createSelectHandler from '../../lib/create_select_handler';
import createTextHandler from '../../lib/create_text_handler';
import FieldSelect from '../../aggs/field_select';
import Select from 'react-select';
import YesNo from '../../yes_no';
import ColorRules from '../../color_rules';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
class TableSeriesConfig extends Component {
@ -58,6 +60,9 @@ class TableSeriesConfig extends Component {
{ label: 'Overall Avg', value: 'overall_avg' },
{ label: 'Cumlative Sum', value: 'cumlative_sum' },
];
const selectedAggFuncOption = functionOptions.find(option => {
return model.aggregate_function === option.value;
});
return (
<div>
@ -101,11 +106,12 @@ class TableSeriesConfig extends Component {
</div>
<label className="vis_editor__label" htmlFor={htmlId('aggregateFunctionInput')}>Aggregate Function</label>
<div className="vis_editor__row_item">
<Select
inputProps={{ id: htmlId('aggregateFunctionInput') }}
value={model.aggregate_function}
<EuiComboBox
id={htmlId('aggregateFunctionInput')}
options={functionOptions}
selectedOptions={selectedAggFuncOption ? [selectedAggFuncOption] : []}
onChange={handleSelectChange('aggregate_function')}
singleSelection={true}
/>
</div>
</div>

View file

@ -19,13 +19,15 @@
import PropTypes from 'prop-types';
import React from 'react';
import Select from 'react-select';
import DataFormatPicker from '../../data_format_picker';
import createSelectHandler from '../../lib/create_select_handler';
import YesNo from '../../yes_no';
import createTextHandler from '../../lib/create_text_handler';
import { IndexPattern } from '../../index_pattern';
import { htmlIdGenerator } from '@elastic/eui';
import {
htmlIdGenerator,
EuiComboBox,
} from '@elastic/eui';
function TimeseriesConfig(props) {
const handleSelectChange = createSelectHandler(props.onChange);
@ -51,21 +53,33 @@ function TimeseriesConfig(props) {
{ label: 'Stacked', value: 'stacked' },
{ label: 'Percent', value: 'percent' }
];
const selectedStackedOption = stackedOptions.find(option => {
return model.stacked === option.value;
});
const positionOptions = [
{ label: 'Right', value: 'right' },
{ label: 'Left', value: 'left' }
];
const selectedAxisPosOption = positionOptions.find(option => {
return model.axis_position === option.value;
});
const chartTypeOptions = [
{ label: 'Bar', value: 'bar' },
{ label: 'Line', value: 'line' }
];
const selectedChartTypeOption = chartTypeOptions.find(option => {
return model.chart_type === option.value;
});
const splitColorOptions = [
{ label: 'Gradient', value: 'gradient' },
{ label: 'Rainbow', value: 'rainbow' }
];
const selectedSplitColorOption = splitColorOptions.find(option => {
return model.split_color_mode === option.value;
});
let type;
if (model.chart_type === 'line') {
@ -75,24 +89,26 @@ function TimeseriesConfig(props) {
Chart Type
</label>
<div className="vis_editor__item">
<Select
inputProps={{ id: htmlId('chartType') }}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('chartType')}
options={chartTypeOptions}
value={model.chart_type}
selectedOptions={selectedChartTypeOption ? [selectedChartTypeOption] : []}
onChange={handleSelectChange('chart_type')}
singleSelection={true}
/>
</div>
<label className="vis_editor__label" htmlFor={htmlId('stacked')}>
Stacked
</label>
<div className="vis_editor__item">
<Select
inputProps={{ id: htmlId('stacked') }}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('stacked')}
options={stackedOptions}
value={model.stacked}
selectedOptions={selectedStackedOption ? [selectedStackedOption] : []}
onChange={handleSelectChange('stacked')}
singleSelection={true}
/>
</div>
<label className="vis_editor__label" htmlFor={htmlId('fill')}>
@ -142,24 +158,26 @@ function TimeseriesConfig(props) {
Chart Type
</label>
<div className="vis_editor__item">
<Select
inputProps={{ id: htmlId('chartType') }}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('chartType')}
options={chartTypeOptions}
value={model.chart_type}
selectedOptions={selectedChartTypeOption ? [selectedChartTypeOption] : []}
onChange={handleSelectChange('chart_type')}
singleSelection={true}
/>
</div>
<label className="vis_editor__label" htmlFor={htmlId('stacked')}>
Stacked
</label>
<div className="vis_editor__item">
<Select
inputProps={{ id: htmlId('stacked') }}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('stacked')}
options={stackedOptions}
value={model.stacked}
selectedOptions={selectedStackedOption ? [selectedStackedOption] : []}
onChange={handleSelectChange('stacked')}
singleSelection={true}
/>
</div>
<label className="vis_editor__label" htmlFor={htmlId('fill')}>
@ -230,12 +248,13 @@ function TimeseriesConfig(props) {
Split Color Theme
</label>
<div className="vis_editor__row_item">
<Select
inputProps={{ id: htmlId('splitColor') }}
clearable={false}
<EuiComboBox
isClearable={false}
id={htmlId('splitColor')}
options={splitColorOptions}
value={model.split_color_mode}
selectedOptions={selectedSplitColorOption ? [selectedSplitColorOption] : []}
onChange={handleSelectChange('split_color_mode')}
singleSelection={true}
/>
</div>
</div>
@ -272,13 +291,14 @@ function TimeseriesConfig(props) {
Axis Position
</label>
<div className="vis_editor__row_item">
<Select
inputProps={{ id: htmlId('axisPos') }}
clearable={false}
disabled={disableSeperateYaxis}
<EuiComboBox
isClearable={false}
isDisabled={disableSeperateYaxis}
id={htmlId('axisPos')}
options={positionOptions}
value={model.axis_position}
selectedOptions={selectedAxisPosOption ? [selectedAxisPosOption] : []}
onChange={handleSelectChange('axis_position')}
singleSelection={true}
/>
</div>
</div>

View file

@ -202,7 +202,6 @@ export const TEMPORARILY_IGNORED_PATHS = [
'src/ui/public/styles/fonts/glyphicons-halflings-regular.woff2',
'src/ui/public/styles/list-group-menu.less',
'src/ui/public/styles/react-input-range.less',
'src/ui/public/styles/react-select.less',
'src/ui/public/styles/theme/font-awesome.less',
'src/ui/public/styles/variables/bootstrap-mods.less',
'src/ui/public/styles/variables/for-theme.less',

View file

@ -3,7 +3,6 @@
@import (reference) "./variables";
@import (reference) "~ui/styles/bootstrap/bootstrap";
@import "./react-input-range";
@import "./react-select";
.small {
font-size: 0.9em !important;

View file

@ -593,83 +593,6 @@
}
}
// react-select
.theme-dark {
.Select-control {
background-color: #444444;
border: 1px solid #444444;
color: #cecece;
}
.is-open > .Select-control {
background: #444444;
border: 1px solid #444444;
}
.is-focused:not(.is-open) > .Select-control {
border-color: #0079a5;
box-shadow: none;
}
.Select-menu-outer {
border: 1px solid #444444;
border-top-color: black;
}
.Select-option {
background-color: #444444;
color: #cecece;
}
.Select--multi .Select-value {
color: #b7e2ea;
border: 1px solid #b7e2ea;
}
.Select--multi .Select-value-icon {
border-right: 1px solid #b7e2ea;
}
.Select-option.is-focused {
background-color: #9c9c9c;
color: #fff;
}
.Select--multi .Select-value-icon:hover,
.Select--multi .Select-value-icon:focus {
color: #444444;
background-color: #b7e2ea;
}
.has-value.Select--single > .Select-control .Select-value .Select-value-label,
.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value .Select-value-label {
color: #cecece;
}
.Select-clear-zone {
color: #a6a6a6;
}
.Select-clear-zone:hover {
color: black;
}
.Select-arrow {
border-color: #a6a6a6 transparent transparent;
}
.is-open > .Select-control .Select-arrow {
border-color: transparent transparent black;
}
.is-open .Select-arrow,
.Select-arrow-zone:hover > .Select-arrow {
border-top-color: black;
}
}
// react-input-range
.theme-dark {
.input-range__track {

View file

@ -1,357 +0,0 @@
.Select {
position: relative;
}
.Select,
.Select div,
.Select input,
.Select span {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.Select.is-disabled > .Select-control {
background-color: #f9f9f9;
}
.Select.is-disabled .Select-arrow-zone {
cursor: default;
pointer-events: none;
opacity: 0.35;
}
.Select-control {
background: #fbfbfb;
color: #3F3F3F;
cursor: default;
display: table;
border-spacing: 0;
border-collapse: separate;
height: 40px;
outline: none;
overflow: hidden;
position: relative;
width: 100%;
font-size: 14px;
border: none;
box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.08), inset -400px 0 0 0 #fbfbfb;
transition: box-shadow 250ms ease-in, background 250ms ease-in, -webkit-box-shadow 250ms ease-in;
border-radius: 0;
}
.Select-control .Select-input:focus {
outline: none;
}
.is-searchable.is-open > .Select-control {
cursor: text;
}
.is-open > .Select-control {
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
background: #fff;
border-color: #DEDEDE;
}
.is-open > .Select-control .Select-arrow {
top: -2px;
border-color: transparent transparent #191E23;
border-width: 0 5px 5px;
}
.is-searchable.is-focused:not(.is-open) > .Select-control {
cursor: text;
}
.is-focused:not(.is-open) > .Select-control {
border-color: #0079a5;
}
.Select-placeholder,
.Select--single > .Select-control .Select-value {
bottom: 0;
color: #757575;
left: 0;
line-height: 34px;
padding-left: 10px;
padding-right: 10px;
position: absolute;
right: 0;
top: 0;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.has-value.Select--single > .Select-control .Select-value .Select-value-label,
.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value .Select-value-label {
color: #333;
}
.has-value.Select--single > .Select-control .Select-value a.Select-value-label,
.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value a.Select-value-label {
cursor: pointer;
text-decoration: none;
}
.has-value.Select--single > .Select-control .Select-value a.Select-value-label:hover,
.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value a.Select-value-label:hover,
.has-value.Select--single > .Select-control .Select-value a.Select-value-label:focus,
.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value a.Select-value-label:focus {
color: #007eff;
outline: none;
text-decoration: underline;
}
.Select-input {
height: 34px;
padding-left: 10px;
padding-right: 10px;
vertical-align: middle;
}
.Select-input > input {
width: 100%;
background: none transparent;
border: 0 none;
box-shadow: none;
cursor: default;
display: inline-block;
font-family: inherit;
font-size: inherit;
margin: 0;
outline: none;
line-height: 14px;
/* For IE 8 compatibility */
padding: 8px 0 12px;
/* For IE 8 compatibility */
-webkit-appearance: none;
}
.is-focused .Select-input > input {
cursor: text;
}
.has-value.is-pseudo-focused .Select-input {
opacity: 0;
}
.Select-control:not(.is-searchable) > .Select-input {
outline: none;
}
.Select-loading-zone {
cursor: pointer;
display: table-cell;
position: relative;
text-align: center;
vertical-align: middle;
width: 16px;
}
.Select-loading {
-webkit-animation: Select-animation-spin 400ms infinite linear;
-o-animation: Select-animation-spin 400ms infinite linear;
animation: Select-animation-spin 400ms infinite linear;
width: 16px;
height: 16px;
box-sizing: border-box;
border-radius: 50%;
border: 2px solid #DEDEDE;
display: inline-block;
position: relative;
vertical-align: middle;
}
.Select-clear-zone {
-webkit-animation: Select-animation-fadeIn 200ms;
-o-animation: Select-animation-fadeIn 200ms;
animation: Select-animation-fadeIn 200ms;
color: #DEDEDE;
cursor: pointer;
display: table-cell;
position: relative;
text-align: center;
vertical-align: middle;
width: 17px;
}
.Select-clear-zone:hover {
color: #191E23;
}
.Select-clear {
display: inline-block;
font-size: 18px;
line-height: 1;
}
.Select--multi .Select-clear-zone {
width: 17px;
}
.Select-arrow-zone {
cursor: pointer;
display: table-cell;
position: relative;
text-align: center;
vertical-align: middle;
width: 25px;
padding-right: 5px;
}
.Select-arrow {
border-color: #DEDEDE transparent transparent;
border-style: solid;
border-width: 5px 5px 2.5px;
display: inline-block;
height: 0;
width: 0;
position: relative;
}
.is-open .Select-arrow,
.Select-arrow-zone:hover > .Select-arrow {
border-top-color: #191E23;
}
.Select--multi .Select-multi-value-wrapper {
display: inline-block;
}
.Select .Select-aria-only {
display: inline-block;
height: 1px;
width: 1px;
margin: -1px;
clip: rect(0, 0, 0, 0);
overflow: hidden;
float: left;
}
@-webkit-keyframes Select-animation-fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes Select-animation-fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.Select-menu-outer {
border-bottom-right-radius: 4px;
border-bottom-left-radius: 4px;
background-color: #fff;
border: 1px solid #DEDEDE;
border-top-color: #DEDEDE;
box-sizing: border-box;
margin-top: -1px;
max-height: 200px;
position: absolute;
top: 100%;
width: 100%;
z-index: 99999;
-webkit-overflow-scrolling: touch;
}
.Select-menu {
max-height: 198px;
overflow-y: auto;
}
.Select-option {
box-sizing: border-box;
background-color: #fff;
color: #666666;
cursor: pointer;
display: block;
padding: 8px 10px;
}
.Select-option:last-child {
border-bottom-right-radius: 4px;
border-bottom-left-radius: 4px;
}
.Select-option.is-selected {
background-color: #f5faff;
/* Fallback color for IE 8 */
background-color: rgba(0, 126, 255, 0.04);
color: #333;
}
.Select-option.is-focused {
background-color: #ebf5ff;
/* Fallback color for IE 8 */
background-color: rgba(0, 126, 255, 0.08);
color: #333;
}
.Select-option.is-disabled {
color: #cccccc;
cursor: default;
}
.Select-noresults {
box-sizing: border-box;
color: #999999;
cursor: default;
display: block;
padding: 8px 10px;
}
.Select--multi .Select-input {
vertical-align: middle;
margin-left: 10px;
padding: 0;
}
.Select--multi.has-value .Select-input {
margin-left: 5px;
}
.Select--multi .Select-value {
background-color: inherit;
border-radius: 2px;
border: 1px solid #0079a5;
color: #0079a5;
display: inline-block;
font-size: 0.9em;
line-height: 1.4;
margin-left: 5px;
margin-top: 5px;
vertical-align: top;
}
.Select--multi .Select-value-icon,
.Select--multi .Select-value-label {
display: inline-block;
vertical-align: middle;
}
.Select--multi .Select-value-label {
border-bottom-right-radius: 2px;
border-top-right-radius: 2px;
cursor: default;
padding: 2px 5px;
}
.Select--multi a.Select-value-label {
color: #0079a5;
cursor: pointer;
text-decoration: none;
}
.Select--multi a.Select-value-label:hover {
text-decoration: underline;
}
.Select--multi .Select-value-icon {
cursor: pointer;
border-bottom-left-radius: 2px;
border-top-left-radius: 2px;
border-right: 1px solid #0079a5;
padding: 1px 5px 3px;
}
.Select--multi .Select-value-icon:hover,
.Select--multi .Select-value-icon:focus {
background-color: #0079a5;
color: #fff;
}
.Select--multi .Select-value-icon:active {
background-color: #c2e0ff;
}
.Select--multi.is-disabled .Select-value {
background-color: #fcfcfc;
border: 1px solid #e3e3e3;
color: #333;
}
.Select--multi.is-disabled .Select-value-icon {
cursor: not-allowed;
border-right: 1px solid #e3e3e3;
}
.Select--multi.is-disabled .Select-value-icon:hover,
.Select--multi.is-disabled .Select-value-icon:focus,
.Select--multi.is-disabled .Select-value-icon:active {
background-color: #fcfcfc;
}
@keyframes Select-animation-spin {
to {
transform: rotate(1turn);
}
}
@-webkit-keyframes Select-animation-spin {
to {
-webkit-transform: rotate(1turn);
}
}
.Select-input {
input:focus {
box-shadow: none;
}
}

View file

@ -24,7 +24,7 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }) {
const retry = getService('retry');
const log = getService('log');
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['common', 'header']);
const PageObjects = getPageObjects(['common', 'header', 'visualize']);
class VisualBuilderPage {
@ -152,12 +152,9 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }) {
});
}
async selectAggType(type, nth = 0) {
async selectAggType(value, nth = 0) {
const elements = await testSubjects.findAll('aggSelector');
const input = await elements[nth].findByCssSelector('.Select-input input');
await input.type(type);
const option = await elements[nth].findByCssSelector('.Select-option');
await option.click();
await PageObjects.visualize.setComboBoxElement(elements[nth], value);
return await PageObjects.header.waitUntilLoadingHasFinished();
}
@ -169,22 +166,17 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }) {
async fillInVariable(name = 'test', metric = 'count', nth = 0) {
const elements = await testSubjects.findAll('varRow');
const input = await elements[nth].findByCssSelector('.vis_editor__calc_vars-name input');
await input.type(name);
const select = await elements[nth].findByCssSelector('.Select-input input');
await select.type(metric);
const option = await elements[nth].findByCssSelector('.Select-option');
await option.click();
const varNameInput = await elements[nth].findByCssSelector('.vis_editor__calc_vars-name input');
await varNameInput.type(name);
const metricSelectWrapper = await elements[nth].findByCssSelector('.vis_editor__calc_vars-var');
await PageObjects.visualize.setComboBoxElement(metricSelectWrapper, metric);
return await PageObjects.header.waitUntilLoadingHasFinished();
}
async selectGroupByField(fieldName) {
const element = await testSubjects.find('groupByField');
const input = await element.findByCssSelector('.Select-input input');
await input.type(fieldName);
const option = await element.findByCssSelector('.Select-option');
await option.click();
await PageObjects.visualize.setComboBoxElement(element, fieldName);
}
async setLabelValue(value) {

View file

@ -219,12 +219,15 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
async setComboBox(comboBoxSelector, value) {
const comboBox = await testSubjects.find(comboBoxSelector);
const input = await comboBox.findByTagName('input');
await this.setComboBoxElement(comboBox, value);
}
async setComboBoxElement(element, value) {
const input = await element.findByTagName('input');
await input.clearValue();
await input.type(value);
await find.clickByCssSelector('.euiComboBoxOption');
await this.closeComboBoxOptionsList(comboBox);
await remote.pressKeys('\uE004');
await this.closeComboBoxOptionsList(element);
}
async getComboBoxOptions(comboBoxSelector) {

View file

@ -10470,7 +10470,7 @@ react-router@^4.2.0:
prop-types "^15.5.4"
warning "^3.0.0"
react-select@^1.2.0, react-select@^1.2.1:
react-select@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.2.1.tgz#a2fe58a569eb14dcaa6543816260b97e538120d1"
dependencies: