EUI input controls visualization (#16210) (#16404)

* update jest tests as best as possible - found some bugs that need to be addressed

* use EuiAccordion to hide/show control editor

* set control editor to be open on load

* small changes

* fix editor jest tests

* update visualization components to EUI

* fix jest tests and updated range control to EUI

* fix bug in range control input logic

* fix button layout

* fix dashboard grid resize test

* add space between panels, change button order, switch to sort icons

* remove style attribute from component, fix spelling of id
This commit is contained in:
Nathan Reese 2018-01-30 11:19:23 -07:00 committed by GitHub
parent 2a927f2a4c
commit 154b096d4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 1003 additions and 826 deletions

View file

@ -55,43 +55,71 @@ exports[`renders ControlsTab 1`] = `
key="2"
moveControl={[Function]}
/>
<div
className="kuiSideBarFormRow"
<EuiPanel
grow={false}
hasShadow={false}
paddingSize="m"
>
<div
className="kuiSideBarFormRow__control kuiFieldGroupSection--wide"
<EuiFlexGroup
alignItems="stretch"
component="div"
gutterSize="l"
justifyContent="flexStart"
responsive={true}
wrap={false}
>
<select
aria-label="Select control type"
className="kuiSelect"
onChange={[Function]}
value="list"
<EuiFlexItem
component="div"
grow={true}
>
<option
value="range"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
id="selectControlType"
>
Range slider
</option>
<option
value="list"
<EuiSelect
fullWidth={false}
isLoading={false}
onChange={[Function]}
options={
Array [
Object {
"text": "Range slider",
"value": "range",
},
Object {
"text": "Options list",
"value": "list",
},
]
}
value="list"
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={false}
>
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
id="addControl"
>
Options list
</option>
</select>
</div>
<KuiButton
buttonType="primary"
data-test-subj="inputControlEditorAddBtn"
icon={
<KuiButtonIcon
type="create"
/>
}
onClick={[Function]}
type="button"
>
Add
</KuiButton>
</div>
<EuiButton
color="primary"
data-test-subj="inputControlEditorAddBtn"
fill={true}
iconSide="left"
iconType="plusInCircle"
onClick={[Function]}
type="button"
>
Add
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</div>
`;

View file

@ -14,48 +14,32 @@ exports[`renders ListControlEditor 1`] = `
onChange={[Function]}
value="keywordField"
/>
<div
className="kuiSideBarFormRow"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
id="multiselect-0"
>
<label
className="kuiSideBarFormRow__label"
htmlFor="multiselect-0"
>
Enable Multiselect
</label>
<div
className="kuiSideBarFormRow__control"
>
<input
checked={true}
className="kuiCheckBox"
id="multiselect-0"
onChange={[Function]}
type="checkbox"
/>
</div>
</div>
<div
className="kuiSideBarFormRow"
<EuiSwitch
checked={true}
data-test-subj="listControlMultiselectInput"
label="Multiselect"
onChange={[Function]}
/>
</EuiFormRow>
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
id="size-0"
label="Size"
>
<label
className="kuiSideBarFormRow__label"
htmlFor="size-0"
>
Size
</label>
<div
className="kuiSideBarFormRow__control kuiFieldGroupSection--wide"
>
<input
className="kuiTextInput"
id="size-0"
min="1"
onChange={[Function]}
type="number"
value={10}
/>
</div>
</div>
<EuiFieldNumber
data-test-subj="listControlSizeInput"
fullWidth={false}
isLoading={false}
min={1}
onChange={[Function]}
value={10}
/>
</EuiFormRow>
</div>
`;

View file

@ -1,67 +1,41 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders OptionsTab 1`] = `
<div>
<div
className="sidebar-item"
<EuiForm>
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
id="updateFiltersOnChange"
>
<div
className="vis-editor-agg-header"
>
<KuiFieldGroup
isAlignedTop={false}
>
<KuiFieldGroupSection
isWide={false}
>
<KuiCheckBoxLabel
data-test-subj="inputControlEditorUpdateFiltersOnChangeCheckbox"
isChecked={false}
isDisabled={false}
onChange={[Function]}
text="Update Kibana filters on each change"
/>
</KuiFieldGroupSection>
</KuiFieldGroup>
</div>
<div
className="vis-editor-agg-header"
>
<KuiFieldGroup
isAlignedTop={false}
>
<KuiFieldGroupSection
isWide={false}
>
<KuiCheckBoxLabel
data-test-subj="inputControlEditorUseTimeFilterCheckbox"
isChecked={false}
isDisabled={false}
onChange={[Function]}
text="Use time filter"
/>
</KuiFieldGroupSection>
</KuiFieldGroup>
</div>
<div
className="vis-editor-agg-header"
>
<KuiFieldGroup
isAlignedTop={false}
>
<KuiFieldGroupSection
isWide={false}
>
<KuiCheckBoxLabel
data-test-subj="inputControlEditorPinFiltersCheckbox"
isChecked={false}
isDisabled={false}
onChange={[Function]}
text="Pin filters to global state"
/>
</KuiFieldGroupSection>
</KuiFieldGroup>
</div>
</div>
</div>
<EuiSwitch
checked={false}
data-test-subj="inputControlEditorUpdateFiltersOnChangeCheckbox"
label="Update Kibana filters on each change"
onChange={[Function]}
/>
</EuiFormRow>
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
id="useTimeFilter"
>
<EuiSwitch
checked={false}
data-test-subj="inputControlEditorUseTimeFilterCheckbox"
label="Use time filter"
onChange={[Function]}
/>
</EuiFormRow>
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
id="pinFilters"
>
<EuiSwitch
data-test-subj="inputControlEditorPinFiltersCheckbox"
label="Pin filters to global state"
onChange={[Function]}
/>
</EuiFormRow>
</EuiForm>
`;

View file

@ -14,48 +14,34 @@ exports[`renders RangeControlEditor 1`] = `
onChange={[Function]}
value="numberField"
/>
<div
className="kuiSideBarFormRow"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
id="stepSize-0"
label="Step Size"
>
<label
className="kuiSideBarFormRow__label"
htmlFor="stepSize-0"
>
Step Size
</label>
<div
className="kuiSideBarFormRow__control kuiFieldGroupSection--wide"
>
<input
className="kuiTextInput"
id="stepSize-0"
onChange={[Function]}
type="number"
value={1}
/>
</div>
</div>
<div
className="kuiSideBarFormRow"
<EuiFieldNumber
data-test-subj="rangeControlSizeInput0"
fullWidth={false}
isLoading={false}
onChange={[Function]}
value={1}
/>
</EuiFormRow>
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
id="decimalPlaces-0"
label="Decimal Places"
>
<label
className="kuiSideBarFormRow__label"
htmlFor="decimalPlaces-0"
>
Decimal Places
</label>
<div
className="kuiSideBarFormRow__control kuiFieldGroupSection--wide"
>
<input
className="kuiTextInput"
id="decimalPlaces-0"
min="0"
onChange={[Function]}
type="number"
value={0}
/>
</div>
</div>
<EuiFieldNumber
data-test-subj="rangeControlDecimalPlacesInput0"
fullWidth={false}
isLoading={false}
min={0}
onChange={[Function]}
value={0}
/>
</EuiFormRow>
</div>
`;

View file

@ -1,22 +1,22 @@
import classNames from 'classnames';
import './control_editor.less';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { RangeControlEditor } from './range_control_editor';
import { ListControlEditor } from './list_control_editor';
import { getTitle } from '../../editor_utils';
import {
EuiAccordion,
EuiButtonIcon,
EuiFieldText,
EuiForm,
EuiFormRow,
EuiPanel,
EuiSpacer,
} from '@elastic/eui';
export class ControlEditor extends Component {
state = {
isEditorCollapsed: true
}
handleToggleControlVisibility = () => {
this.setState(prevState => (
{ isEditorCollapsed: !prevState.isEditorCollapsed }
));
}
changeLabel = (evt) => {
this.props.handleLabelChange(this.props.controlIndex, evt);
}
@ -77,80 +77,65 @@ export class ControlEditor extends Component {
const labelId = `controlLabel${this.props.controlIndex}`;
return (
<div>
<div className="kuiSideBarFormRow">
<label className="kuiSideBarFormRow__label" htmlFor={labelId}>
Label
</label>
<div className="kuiSideBarFormRow__control kuiFieldGroupSection--wide">
<input
className="kuiTextInput"
id={labelId}
type="text"
value={this.props.controlParams.label}
onChange={this.changeLabel}
/>
</div>
</div>
<EuiForm>
<EuiFormRow
id={labelId}
label="Control Label"
>
<EuiFieldText
value={this.props.controlParams.label}
onChange={this.changeLabel}
/>
</EuiFormRow>
{controlEditor}
</EuiForm>
);
}
renderEditorButtons() {
return (
<div>
<EuiButtonIcon
aria-label="Move control down"
color="primary"
onClick={this.moveDownControl}
iconType="sortUp"
data-test-subj={`inputControlEditorMoveDownControl${this.props.controlIndex}`}
/>
<EuiButtonIcon
aria-label="Move control up"
color="primary"
onClick={this.moveUpControl}
iconType="sortDown"
data-test-subj={`inputControlEditorMoveUpControl${this.props.controlIndex}`}
/>
<EuiButtonIcon
aria-label="Remove control"
color="danger"
onClick={this.removeControl}
iconType="cross"
data-test-subj={`inputControlEditorRemoveControl${this.props.controlIndex}`}
/>
</div>
);
}
render() {
const visibilityToggleClasses = classNames('fa', {
'fa-caret-right': !this.state.isEditorCollapsed,
'fa-caret-down': this.state.isEditorCollapsed
});
return (
<div className="sidebar-item">
<div className="vis-editor-agg-header">
<button
aria-label={this.state.isEditorCollapsed ? 'Close Editor' : 'Open Editor'}
onClick={this.handleToggleControlVisibility}
type="button"
className="kuiButton kuiButton--primary kuiButton--small vis-editor-agg-header-toggle"
>
<i aria-hidden="true" className={visibilityToggleClasses} />
</button>
<span className="vis-editor-agg-header-title ng-binding">
{getTitle(this.props.controlParams, this.props.controlIndex)}
</span>
<div className="vis-editor-agg-header-controls kuiButtonGroup kuiButtonGroup--united">
<button
aria-label="Move control down"
type="button"
className="kuiButton kuiButton--small"
onClick={this.moveDownControl}
data-test-subj={`inputControlEditorMoveDownControl${this.props.controlIndex}`}
>
<i aria-hidden="true" className="fa fa-chevron-down" />
</button>
<button
aria-label="Move control up"
type="button"
className="kuiButton kuiButton--small"
onClick={this.moveUpControl}
data-test-subj={`inputControlEditorMoveUpControl${this.props.controlIndex}`}
>
<i aria-hidden="true" className="fa fa-chevron-up" />
</button>
<button
aria-label="Remove control"
className="kuiButton kuiButton--danger kuiButton--small"
type="button"
onClick={this.removeControl}
data-test-subj={`inputControlEditorRemoveControl${this.props.controlIndex}`}
>
<i aria-hidden="true" className="fa fa-times" />
</button>
</div>
</div>
<EuiPanel grow={false} className="controlEditorPanel">
{this.state.isEditorCollapsed && this.renderEditor()}
</div>
<EuiAccordion
id="controlEditorAccordion"
buttonContent={getTitle(this.props.controlParams, this.props.controlIndex)}
extraAction={this.renderEditorButtons()}
initialIsOpen={true}
>
<EuiSpacer size="s" />
{this.renderEditor()}
</EuiAccordion>
</EuiPanel>
);
}
}

View file

@ -0,0 +1,4 @@
.controlEditorPanel {
z-index: 1;
margin-bottom: 8px;
}

View file

@ -1,10 +1,19 @@
import './controls_tab.less';
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { ControlEditor } from './control_editor';
import { KuiButton, KuiButtonIcon } from 'ui_framework/components';
import { addControl, moveControl, newControl, removeControl, setControl } from '../../editor_utils';
import {
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
EuiPanel,
EuiSelect,
} from '@elastic/eui';
export class ControlsTab extends Component {
state = {
@ -103,28 +112,39 @@ export class ControlsTab extends Component {
{this.renderControls()}
<div className="kuiSideBarFormRow">
<div className="kuiSideBarFormRow__control kuiFieldGroupSection--wide">
<select
aria-label="Select control type"
className="kuiSelect"
value={this.state.type}
onChange={evt => this.setState({ type: evt.target.value })}
>
<option value="range">Range slider</option>
<option value="list">Options list</option>
</select>
</div>
<KuiButton
buttonType="primary"
type="button"
icon={<KuiButtonIcon type="create" />}
onClick={this.handleAddControl}
data-test-subj="inputControlEditorAddBtn"
>
Add
</KuiButton>
</div>
<EuiPanel grow={false}>
<EuiFlexGroup>
<EuiFlexItem>
<EuiFormRow
id="selectControlType"
>
<EuiSelect
options={[
{ value: 'range', text: 'Range slider' },
{ value: 'list', text: 'Options list' },
]}
value={this.state.type}
onChange={evt => this.setState({ type: evt.target.value })}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFormRow
id="addControl"
>
<EuiButton
fill
onClick={this.handleAddControl}
iconType="plusInCircle"
data-test-subj="inputControlEditorAddBtn"
>
Add
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</div>
);
}

View file

@ -0,0 +1,3 @@
.euiAccordion__childWrapper {
overflow: visible;
}

View file

@ -2,7 +2,11 @@ import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Select from 'react-select';
import { htmlIdGenerator } from '@elastic/eui';
import {
EuiFormRow,
htmlIdGenerator,
} from '@elastic/eui';
export class FieldSelect extends Component {
constructor(props) {
@ -60,24 +64,22 @@ export class FieldSelect extends Component {
}
const idGenerator = htmlIdGenerator();
const selectId = idGenerator('indexPatternSelect');
const selectId = idGenerator('fieldSelect');
return (
<div className="kuiSideBarFormRow">
<label className="kuiSideBarFormRow__label" htmlFor={selectId}>
Field
</label>
<div className="kuiSideBarFormRow__control kuiFieldGroupSection--wide">
<Select
className="field-react-select"
placeholder="Select field..."
value={this.props.value}
options={this.state.fields}
onChange={this.props.onChange}
resetValue={''}
inputProps={{ id: selectId }}
/>
</div>
</div>
<EuiFormRow
id={selectId}
label="Field"
>
<Select
className="field-react-select"
placeholder="Select field..."
value={this.props.value}
options={this.state.fields}
onChange={this.props.onChange}
resetValue={''}
inputProps={{ id: selectId }}
/>
</EuiFormRow>
);
}
}

View file

@ -1,7 +1,11 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Select from 'react-select';
import { htmlIdGenerator } from '@elastic/eui';
import {
EuiFormRow,
htmlIdGenerator,
} from '@elastic/eui';
export class IndexPatternSelect extends Component {
constructor(props) {
@ -26,22 +30,20 @@ export class IndexPatternSelect extends Component {
const idGenerator = htmlIdGenerator();
const selectId = idGenerator('indexPatternSelect');
return (
<div className="kuiSideBarFormRow">
<label className="kuiSideBarFormRow__label" htmlFor={selectId}>
Index Pattern
</label>
<div className="kuiSideBarFormRow__control kuiFieldGroupSection--wide">
<Select.Async
className="index-pattern-react-select"
placeholder="Select index pattern..."
value={this.props.value}
loadOptions={this.loadOptions}
onChange={this.props.onChange}
resetValue={''}
inputProps={{ id: selectId }}
/>
</div>
</div>
<EuiFormRow
id={selectId}
label="Index Pattern"
>
<Select.Async
className="index-pattern-react-select"
placeholder="Select index pattern..."
value={this.props.value}
loadOptions={this.loadOptions}
onChange={this.props.onChange}
resetValue={''}
inputProps={{ id: selectId }}
/>
</EuiFormRow>
);
}
}

View file

@ -3,6 +3,12 @@ import React from 'react';
import { IndexPatternSelect } from './index_pattern_select';
import { FieldSelect } from './field_select';
import {
EuiFormRow,
EuiFieldNumber,
EuiSwitch,
} from '@elastic/eui';
function filterField(field) {
return field.aggregatable && ['number', 'boolean', 'date', 'ip', 'string'].includes(field.type);
}
@ -34,36 +40,28 @@ export function ListControlEditor(props) {
getIndexPattern={props.getIndexPattern}
/>
<div className="kuiSideBarFormRow">
<label className="kuiSideBarFormRow__label" htmlFor={multiselectId}>
Enable Multiselect
</label>
<div className="kuiSideBarFormRow__control">
<input
id={multiselectId}
className="kuiCheckBox"
type="checkbox"
checked={props.controlParams.options.multiselect}
onChange={handleMultiselectChange}
/>
</div>
</div>
<EuiFormRow
id={multiselectId}
>
<EuiSwitch
label="Multiselect"
checked={props.controlParams.options.multiselect}
onChange={handleMultiselectChange}
data-test-subj="listControlMultiselectInput"
/>
</EuiFormRow>
<div className="kuiSideBarFormRow">
<label className="kuiSideBarFormRow__label" htmlFor={sizeId}>
Size
</label>
<div className="kuiSideBarFormRow__control kuiFieldGroupSection--wide">
<input
id={sizeId}
className="kuiTextInput"
type="number"
min="1"
value={props.controlParams.options.size}
onChange={handleSizeChange}
/>
</div>
</div>
<EuiFormRow
id={sizeId}
label="Size"
>
<EuiFieldNumber
min={1}
value={props.controlParams.options.size}
onChange={handleSizeChange}
data-test-subj="listControlSizeInput"
/>
</EuiFormRow>
</div>
);

View file

@ -1,6 +1,7 @@
import React from 'react';
import sinon from 'sinon';
import { mount, shallow } from 'enzyme';
import { findTestSubject } from '@elastic/eui/lib/test';
import {
ListControlEditor,
@ -82,7 +83,7 @@ test('handleCheckboxOptionChange - multiselect', () => {
handleCheckboxOptionChange={handleCheckboxOptionChange}
handleNumberOptionChange={handleNumberOptionChange}
/>);
const checkbox = component.find('#multiselect-0');
const checkbox = findTestSubject(component, 'listControlMultiselectInput');
checkbox.simulate('change', { target: { checked: true } });
sinon.assert.notCalled(handleFieldNameChange);
sinon.assert.notCalled(handleIndexPatternChange);
@ -112,7 +113,7 @@ test('handleNumberOptionChange - size', () => {
handleCheckboxOptionChange={handleCheckboxOptionChange}
handleNumberOptionChange={handleNumberOptionChange}
/>);
const input = component.find('#size-0');
const input = findTestSubject(component, 'listControlSizeInput');
input.simulate('change', { target: { value: 7 } });
sinon.assert.notCalled(handleCheckboxOptionChange);
sinon.assert.notCalled(handleFieldNameChange);

View file

@ -1,10 +1,12 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import {
KuiFieldGroup,
KuiFieldGroupSection,
KuiCheckBoxLabel } from 'ui_framework/components';
EuiForm,
EuiFormRow,
EuiSwitch,
} from '@elastic/eui';
export class OptionsTab extends Component {
@ -28,50 +30,40 @@ export class OptionsTab extends Component {
render() {
return (
<div>
<EuiForm>
<EuiFormRow
id="updateFiltersOnChange"
>
<EuiSwitch
label="Update Kibana filters on each change"
checked={this.props.scope.vis.params.updateFiltersOnChange}
onChange={this.handleUpdateFiltersChange}
data-test-subj="inputControlEditorUpdateFiltersOnChangeCheckbox"
/>
</EuiFormRow>
<div className="sidebar-item">
<div className="vis-editor-agg-header">
<KuiFieldGroup>
<KuiFieldGroupSection>
<KuiCheckBoxLabel
text="Update Kibana filters on each change"
isChecked={this.props.scope.vis.params.updateFiltersOnChange}
onChange={this.handleUpdateFiltersChange}
data-test-subj="inputControlEditorUpdateFiltersOnChangeCheckbox"
/>
</KuiFieldGroupSection>
</KuiFieldGroup>
</div>
<EuiFormRow
id="useTimeFilter"
>
<EuiSwitch
label="Use time filter"
checked={this.props.scope.vis.params.useTimeFilter}
onChange={this.handleUseTimeFilter}
data-test-subj="inputControlEditorUseTimeFilterCheckbox"
/>
</EuiFormRow>
<div className="vis-editor-agg-header">
<KuiFieldGroup>
<KuiFieldGroupSection>
<KuiCheckBoxLabel
text="Use time filter"
isChecked={this.props.scope.vis.params.useTimeFilter}
onChange={this.handleUseTimeFilter}
data-test-subj="inputControlEditorUseTimeFilterCheckbox"
/>
</KuiFieldGroupSection>
</KuiFieldGroup>
</div>
<div className="vis-editor-agg-header">
<KuiFieldGroup>
<KuiFieldGroupSection>
<KuiCheckBoxLabel
text="Pin filters to global state"
isChecked={this.props.scope.vis.params.pinFilters}
onChange={this.handlePinFilters}
data-test-subj="inputControlEditorPinFiltersCheckbox"
/>
</KuiFieldGroupSection>
</KuiFieldGroup>
</div>
</div>
</div>
<EuiFormRow
id="pinFilters"
>
<EuiSwitch
label="Pin filters to global state"
checked={this.props.scope.vis.params.pinFilters}
onChange={this.handlePinFilters}
data-test-subj="inputControlEditorPinFiltersCheckbox"
/>
</EuiFormRow>
</EuiForm>
);
}
}

View file

@ -3,6 +3,11 @@ import React from 'react';
import { IndexPatternSelect } from './index_pattern_select';
import { FieldSelect } from './field_select';
import {
EuiFormRow,
EuiFieldNumber,
} from '@elastic/eui';
function filterField(field) {
return field.type === 'number';
}
@ -33,36 +38,28 @@ export function RangeControlEditor(props) {
getIndexPattern={props.getIndexPattern}
/>
<div className="kuiSideBarFormRow">
<label className="kuiSideBarFormRow__label" htmlFor={stepSizeId}>
Step Size
</label>
<div className="kuiSideBarFormRow__control kuiFieldGroupSection--wide">
<input
id={stepSizeId}
className="kuiTextInput"
type="number"
value={props.controlParams.options.step}
onChange={handleStepChange}
/>
</div>
</div>
<EuiFormRow
id={stepSizeId}
label="Step Size"
>
<EuiFieldNumber
value={props.controlParams.options.step}
onChange={handleStepChange}
data-test-subj={`rangeControlSizeInput${props.controlIndex}`}
/>
</EuiFormRow>
<div className="kuiSideBarFormRow">
<label className="kuiSideBarFormRow__label" htmlFor={decimalPlacesId}>
Decimal Places
</label>
<div className="kuiSideBarFormRow__control kuiFieldGroupSection--wide">
<input
id={decimalPlacesId}
className="kuiTextInput"
type="number"
min="0"
value={props.controlParams.options.decimalPlaces}
onChange={handleDecimalPlacesChange}
/>
</div>
</div>
<EuiFormRow
id={decimalPlacesId}
label="Decimal Places"
>
<EuiFieldNumber
min={0}
value={props.controlParams.options.decimalPlaces}
onChange={handleDecimalPlacesChange}
data-test-subj={`rangeControlDecimalPlacesInput${props.controlIndex}`}
/>
</EuiFormRow>
</div>
);

View file

@ -1,6 +1,7 @@
import React from 'react';
import sinon from 'sinon';
import { mount, shallow } from 'enzyme';
import { findTestSubject } from '@elastic/eui/lib/test';
import {
RangeControlEditor,
@ -77,8 +78,7 @@ test('handleNumberOptionChange - step', () => {
handleIndexPatternChange={handleIndexPatternChange}
handleNumberOptionChange={handleNumberOptionChange}
/>);
const input = component.find('#stepSize-0');
input.simulate('change', { target: { value: 0.5 } });
findTestSubject(component, 'rangeControlSizeInput0').simulate('change', { target: { value: 0.5 } });
sinon.assert.notCalled(handleFieldNameChange);
sinon.assert.notCalled(handleIndexPatternChange);
const expectedControlIndex = 0;
@ -105,8 +105,7 @@ test('handleNumberOptionChange - decimalPlaces', () => {
handleIndexPatternChange={handleIndexPatternChange}
handleNumberOptionChange={handleNumberOptionChange}
/>);
const input = component.find('#decimalPlaces-0');
input.simulate('change', { target: { value: 2 } });
findTestSubject(component, 'rangeControlDecimalPlacesInput0').simulate('change', { target: { value: 2 } });
sinon.assert.notCalled(handleFieldNameChange);
sinon.assert.notCalled(handleIndexPatternChange);
const expectedControlIndex = 0;

View file

@ -1,60 +1,46 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders disabled control with tooltip 1`] = `
<div
className="kuiVerticalRhythm"
<EuiFormRow
data-test-subj="inputControl0"
fullWidth={false}
hasEmptyLabelSpace={false}
id="controlId"
label="test control"
>
<label
className="kuiLabel kuiVerticalRhythmSmall"
htmlFor="controlId"
>
test control
</label>
<div
className="kuiVerticalRhythmSmall"
>
<OverlayTrigger
display={false}
isSticky={false}
overlay={
<Tooltip
className="inputControlDisabledTooltip"
isSticky={false}
size="auto"
visible={true}
/>
}
pin={true}
placement="top"
theme="dark"
trigger="hover"
>
<div>
My Control
</div>
</OverlayTrigger>
</div>
</div>
`;
exports[`renders enabled control 1`] = `
<div
className="kuiVerticalRhythm"
data-test-subj="inputControl0"
>
<label
className="kuiLabel kuiVerticalRhythmSmall"
htmlFor="controlId"
>
test control
</label>
<div
className="kuiVerticalRhythmSmall"
<OverlayTrigger
display={false}
isSticky={false}
overlay={
<Tooltip
className="inputControlDisabledTooltip"
isSticky={false}
size="auto"
visible={true}
/>
}
pin={true}
placement="top"
theme="dark"
trigger="hover"
>
<div>
My Control
</div>
</div>
</div>
</OverlayTrigger>
</EuiFormRow>
`;
exports[`renders enabled control 1`] = `
<EuiFormRow
data-test-subj="inputControl0"
fullWidth={false}
hasEmptyLabelSpace={false}
id="controlId"
label="test control"
>
<div>
My Control
</div>
</EuiFormRow>
`;

View file

@ -4,13 +4,17 @@ exports[`Apply and Cancel change btns enabled when there are changes 1`] = `
<div
className="inputControlVis"
>
<KuiFlexGroup
<EuiFlexGroup
alignItems="stretch"
gutterSize="large"
component="div"
gutterSize="l"
justifyContent="flexStart"
responsive={true}
wrap={true}
>
<KuiFlexItem
<EuiFlexItem
component="div"
data-test-subj="inputControlItem"
grow={true}
key="mock-list-control"
style={
@ -47,52 +51,80 @@ exports[`Apply and Cancel change btns enabled when there are changes 1`] = `
controlIndex={0}
stageFilter={[Function]}
/>
</KuiFlexItem>
</KuiFlexGroup>
<KuiFieldGroup
className="actions"
isAlignedTop={false}
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup
alignItems="stretch"
component="div"
gutterSize="l"
justifyContent="flexStart"
responsive={true}
wrap={false}
>
<KuiFieldGroupSection
isWide={false}
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="primary"
data-test-subj="inputControlSubmitBtn"
disabled={false}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Apply changes
</KuiButton>
</KuiFieldGroupSection>
<KuiFieldGroupSection
isWide={false}
<EuiButton
color="primary"
data-test-subj="inputControlClearBtn"
disabled={true}
fill={false}
iconSide="left"
onClick={[Function]}
type="button"
>
Clear form
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="basic"
data-test-subj="inputControlCancelBtn"
disabled={false}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Cancel changes
</KuiButton>
</KuiFieldGroupSection>
<KuiFieldGroupSection
isWide={false}
<EuiButton
color="primary"
data-test-subj="inputControlCancelBtn"
disabled={false}
fill={false}
iconSide="left"
onClick={[Function]}
type="button"
>
Cancel changes
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="basic"
data-test-subj="inputControlClearBtn"
disabled={true}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Clear form
</KuiButton>
</KuiFieldGroupSection>
</KuiFieldGroup>
<EuiButton
color="primary"
data-test-subj="inputControlSubmitBtn"
disabled={false}
fill={true}
iconSide="left"
onClick={[Function]}
type="button"
>
Apply changes
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</div>
`;
@ -100,13 +132,17 @@ exports[`Clear btns enabled when there are values 1`] = `
<div
className="inputControlVis"
>
<KuiFlexGroup
<EuiFlexGroup
alignItems="stretch"
gutterSize="large"
component="div"
gutterSize="l"
justifyContent="flexStart"
responsive={true}
wrap={true}
>
<KuiFlexItem
<EuiFlexItem
component="div"
data-test-subj="inputControlItem"
grow={true}
key="mock-list-control"
style={
@ -143,52 +179,80 @@ exports[`Clear btns enabled when there are values 1`] = `
controlIndex={0}
stageFilter={[Function]}
/>
</KuiFlexItem>
</KuiFlexGroup>
<KuiFieldGroup
className="actions"
isAlignedTop={false}
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup
alignItems="stretch"
component="div"
gutterSize="l"
justifyContent="flexStart"
responsive={true}
wrap={false}
>
<KuiFieldGroupSection
isWide={false}
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="primary"
data-test-subj="inputControlSubmitBtn"
disabled={true}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Apply changes
</KuiButton>
</KuiFieldGroupSection>
<KuiFieldGroupSection
isWide={false}
<EuiButton
color="primary"
data-test-subj="inputControlClearBtn"
disabled={false}
fill={false}
iconSide="left"
onClick={[Function]}
type="button"
>
Clear form
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="basic"
data-test-subj="inputControlCancelBtn"
disabled={true}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Cancel changes
</KuiButton>
</KuiFieldGroupSection>
<KuiFieldGroupSection
isWide={false}
<EuiButton
color="primary"
data-test-subj="inputControlCancelBtn"
disabled={true}
fill={false}
iconSide="left"
onClick={[Function]}
type="button"
>
Cancel changes
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="basic"
data-test-subj="inputControlClearBtn"
disabled={false}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Clear form
</KuiButton>
</KuiFieldGroupSection>
</KuiFieldGroup>
<EuiButton
color="primary"
data-test-subj="inputControlSubmitBtn"
disabled={true}
fill={true}
iconSide="left"
onClick={[Function]}
type="button"
>
Apply changes
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</div>
`;
@ -196,13 +260,17 @@ exports[`Renders list control 1`] = `
<div
className="inputControlVis"
>
<KuiFlexGroup
<EuiFlexGroup
alignItems="stretch"
gutterSize="large"
component="div"
gutterSize="l"
justifyContent="flexStart"
responsive={true}
wrap={true}
>
<KuiFlexItem
<EuiFlexItem
component="div"
data-test-subj="inputControlItem"
grow={true}
key="mock-list-control"
style={
@ -239,52 +307,80 @@ exports[`Renders list control 1`] = `
controlIndex={0}
stageFilter={[Function]}
/>
</KuiFlexItem>
</KuiFlexGroup>
<KuiFieldGroup
className="actions"
isAlignedTop={false}
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup
alignItems="stretch"
component="div"
gutterSize="l"
justifyContent="flexStart"
responsive={true}
wrap={false}
>
<KuiFieldGroupSection
isWide={false}
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="primary"
data-test-subj="inputControlSubmitBtn"
disabled={true}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Apply changes
</KuiButton>
</KuiFieldGroupSection>
<KuiFieldGroupSection
isWide={false}
<EuiButton
color="primary"
data-test-subj="inputControlClearBtn"
disabled={true}
fill={false}
iconSide="left"
onClick={[Function]}
type="button"
>
Clear form
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="basic"
data-test-subj="inputControlCancelBtn"
disabled={true}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Cancel changes
</KuiButton>
</KuiFieldGroupSection>
<KuiFieldGroupSection
isWide={false}
<EuiButton
color="primary"
data-test-subj="inputControlCancelBtn"
disabled={true}
fill={false}
iconSide="left"
onClick={[Function]}
type="button"
>
Cancel changes
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="basic"
data-test-subj="inputControlClearBtn"
disabled={true}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Clear form
</KuiButton>
</KuiFieldGroupSection>
</KuiFieldGroup>
<EuiButton
color="primary"
data-test-subj="inputControlSubmitBtn"
disabled={true}
fill={true}
iconSide="left"
onClick={[Function]}
type="button"
>
Apply changes
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</div>
`;
@ -292,13 +388,17 @@ exports[`Renders range control 1`] = `
<div
className="inputControlVis"
>
<KuiFlexGroup
<EuiFlexGroup
alignItems="stretch"
gutterSize="large"
component="div"
gutterSize="l"
justifyContent="flexStart"
responsive={true}
wrap={true}
>
<KuiFlexItem
<EuiFlexItem
component="div"
data-test-subj="inputControlItem"
grow={true}
key="mock-range-control"
style={
@ -329,51 +429,79 @@ exports[`Renders range control 1`] = `
controlIndex={0}
stageFilter={[Function]}
/>
</KuiFlexItem>
</KuiFlexGroup>
<KuiFieldGroup
className="actions"
isAlignedTop={false}
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup
alignItems="stretch"
component="div"
gutterSize="l"
justifyContent="flexStart"
responsive={true}
wrap={false}
>
<KuiFieldGroupSection
isWide={false}
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="primary"
data-test-subj="inputControlSubmitBtn"
disabled={true}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Apply changes
</KuiButton>
</KuiFieldGroupSection>
<KuiFieldGroupSection
isWide={false}
<EuiButton
color="primary"
data-test-subj="inputControlClearBtn"
disabled={true}
fill={false}
iconSide="left"
onClick={[Function]}
type="button"
>
Clear form
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="basic"
data-test-subj="inputControlCancelBtn"
disabled={true}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Cancel changes
</KuiButton>
</KuiFieldGroupSection>
<KuiFieldGroupSection
isWide={false}
<EuiButton
color="primary"
data-test-subj="inputControlCancelBtn"
disabled={true}
fill={false}
iconSide="left"
onClick={[Function]}
type="button"
>
Cancel changes
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={false}
>
<KuiButton
buttonType="basic"
data-test-subj="inputControlClearBtn"
disabled={true}
onClick={[Function]}
type="button"
<EuiFormRow
fullWidth={false}
hasEmptyLabelSpace={false}
>
Clear form
</KuiButton>
</KuiFieldGroupSection>
</KuiFieldGroup>
<EuiButton
color="primary"
data-test-subj="inputControlSubmitBtn"
disabled={true}
fill={true}
iconSide="left"
onClick={[Function]}
type="button"
>
Apply changes
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
</div>
`;

View file

@ -25,65 +25,91 @@ exports[`renders RangeControl 1`] = `
id="mock-range-control"
label="range control"
>
<div>
<input
className="kuiTextInput"
disabled={false}
id="mock-range-control_min"
max={100}
min={0}
name="min"
onChange={[Function]}
type="number"
value=""
/>
<div
className="inputRangeContainer"
<EuiFormRow
error={Array []}
fullWidth={false}
hasEmptyLabelSpace={false}
isInvalid={false}
>
<EuiFlexGroup
alignItems="stretch"
component="div"
gutterSize="l"
justifyContent="flexStart"
responsive={true}
wrap={false}
>
<InputRange
allowSameValues={false}
ariaLabelledby="mock-range-control"
classNames={
Object {
"activeTrack": "input-range__track input-range__track--active",
"disabledInputRange": "input-range input-range--disabled",
"inputRange": "input-range",
"labelContainer": "input-range__label-container",
"maxLabel": "input-range__label input-range__label--max",
"minLabel": "input-range__label input-range__label--min",
"slider": "input-range__slider",
"sliderContainer": "input-range__slider-container",
"track": "input-range__track input-range__track--background",
"valueLabel": "input-range__label input-range__label--value",
<EuiFlexItem
component="div"
grow={false}
>
<input
className="euiFieldNumber"
disabled={false}
id="mock-range-control_min"
max={100}
min={0}
name="min"
onChange={[Function]}
type="number"
value=""
/>
</EuiFlexItem>
<EuiFlexItem
className="inputRangeContainer"
component="div"
grow={true}
>
<InputRange
allowSameValues={false}
ariaLabelledby="mock-range-control"
classNames={
Object {
"activeTrack": "input-range__track input-range__track--active",
"disabledInputRange": "input-range input-range--disabled",
"inputRange": "input-range",
"labelContainer": "input-range__label-container",
"maxLabel": "input-range__label input-range__label--max",
"minLabel": "input-range__label input-range__label--min",
"slider": "input-range__slider",
"sliderContainer": "input-range__slider-container",
"track": "input-range__track input-range__track--background",
"valueLabel": "input-range__label input-range__label--value",
}
}
}
disabled={false}
draggableTrack={true}
formatLabel={[Function]}
maxValue={100}
minValue={0}
onChange={[Function]}
onChangeComplete={[Function]}
step={1}
value={
Object {
"max": 0,
"min": 0,
disabled={false}
draggableTrack={true}
formatLabel={[Function]}
maxValue={100}
minValue={0}
onChange={[Function]}
onChangeComplete={[Function]}
step={1}
value={
Object {
"max": 0,
"min": 0,
}
}
}
/>
</div>
<input
className="kuiTextInput"
disabled={false}
id="mock-range-control_max"
max={100}
min={0}
name="max"
onChange={[Function]}
type="number"
value=""
/>
</div>
/>
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={false}
>
<input
className="euiFieldNumber"
disabled={false}
id="mock-range-control_max"
max={100}
min={0}
name="max"
onChange={[Function]}
type="number"
value=""
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFormRow>
</FormRow>
`;

View file

@ -3,6 +3,10 @@ import React from 'react';
import { Tooltip } from 'pivotal-ui/react/tooltip';
import { OverlayTrigger } from 'pivotal-ui/react/overlay-trigger';
import {
EuiFormRow,
} from '@elastic/eui';
export function FormRow(props) {
let control = props.children;
if (!props.control.isEnabled()) {
@ -17,17 +21,13 @@ export function FormRow(props) {
}
return (
<div
className="kuiVerticalRhythm"
<EuiFormRow
label={props.label}
id={props.id}
data-test-subj={'inputControl' + props.controlIndex}
>
<label className="kuiLabel kuiVerticalRhythmSmall" htmlFor={props.id}>
{props.label}
</label>
<div className="kuiVerticalRhythmSmall">
{control}
</div>
</div>
{control}
</EuiFormRow>
);
}

View file

@ -3,12 +3,11 @@ import React, { Component } from 'react';
import { RangeControl } from './range_control';
import { ListControl } from './list_control';
import {
KuiFieldGroup,
KuiFieldGroupSection,
KuiButton,
KuiFlexGroup,
KuiFlexItem
} from 'ui_framework/components';
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
} from '@elastic/eui';
export class InputControlVis extends Component {
constructor(props) {
@ -58,50 +57,55 @@ export class InputControlVis extends Component {
throw new Error(`Unhandled control type ${control.type}`);
}
return (
<KuiFlexItem key={control.id} style={{ minWidth: '250px' }}>
<EuiFlexItem
key={control.id}
style={{ minWidth: '250px' }}
data-test-subj="inputControlItem"
>
{controlComponent}
</KuiFlexItem>
</EuiFlexItem>
);
});
}
renderStagingButtons() {
return (
<KuiFieldGroup className="actions">
<KuiFieldGroupSection>
<KuiButton
buttonType="primary"
type="button"
onClick={this.handleSubmit}
disabled={!this.props.hasChanges()}
data-test-subj="inputControlSubmitBtn"
>
Apply changes
</KuiButton>
</KuiFieldGroupSection>
<KuiFieldGroupSection>
<KuiButton
buttonType="basic"
type="button"
onClick={this.handleReset}
disabled={!this.props.hasChanges()}
data-test-subj="inputControlCancelBtn"
>
Cancel changes
</KuiButton>
</KuiFieldGroupSection>
<KuiFieldGroupSection>
<KuiButton
buttonType="basic"
type="button"
onClick={this.handleClearAll}
disabled={!this.props.hasValues()}
data-test-subj="inputControlClearBtn"
>
Clear form
</KuiButton>
</KuiFieldGroupSection>
</KuiFieldGroup>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiFormRow>
<EuiButton
onClick={this.handleClearAll}
disabled={!this.props.hasValues()}
data-test-subj="inputControlClearBtn"
>
Clear form
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFormRow>
<EuiButton
onClick={this.handleReset}
disabled={!this.props.hasChanges()}
data-test-subj="inputControlCancelBtn"
>
Cancel changes
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFormRow>
<EuiButton
fill
onClick={this.handleSubmit}
disabled={!this.props.hasChanges()}
data-test-subj="inputControlSubmitBtn"
>
Apply changes
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
);
}
@ -113,9 +117,9 @@ export class InputControlVis extends Component {
return (
<div className="inputControlVis">
<KuiFlexGroup wrap>
<EuiFlexGroup wrap>
{this.renderControls()}
</KuiFlexGroup>
</EuiFlexGroup>
{stagingButtons}
</div>
);

View file

@ -4,11 +4,20 @@ import React, { Component } from 'react';
import InputRange from 'react-input-range';
import { FormRow } from './form_row';
import {
EuiFormRow,
EuiFlexGroup,
EuiFlexItem,
} from '@elastic/eui';
const toState = (props) => {
const state = {
sliderValue: props.control.value,
minValue: '',
maxValue: ''
isMinValid: true,
maxValue: '',
isMaxValid: true,
errorMsgs: [],
};
if (props.control.hasValue()) {
state.minValue = props.control.value.min;
@ -32,7 +41,10 @@ export class RangeControl extends Component {
this.setState({
sliderValue: value,
minValue: value.min,
maxValue: value.max
isMinValid: true,
maxValue: value.max,
isMaxValid: true,
errorMsgs: [],
});
}
@ -40,30 +52,72 @@ export class RangeControl extends Component {
this.props.stageFilter(this.props.controlIndex, value);
}
handleInputChange = (evt) => {
let inputValue = parseFloat(evt.target.value);
if (inputValue < this.props.control.min) {
inputValue = this.props.control.min;
} else if (inputValue > this.props.control.max) {
inputValue = this.props.control.max;
handleMinChange = (evt) => {
const min = parseFloat(evt.target.value);
const max = this.state.maxValue;
if (isNaN(min)) {
if (max === '') {
this.setState({
minValue: '',
isMinValid: true,
maxValue: '',
isMaxValid: true,
errorMsgs: [],
});
return;
}
this.setState({
minValue: '',
isMinValid: false,
errorMsgs: ['both min and max must be set'],
});
return;
} else if (min > max) {
this.setState({
minValue: min,
isMinValid: false,
errorMsgs: ['min must be less than max'],
});
return;
}
let otherValue;
if ('min' === evt.target.name) {
otherValue = this.props.control.value.max;
} else {
otherValue = this.props.control.value.min;
this.handleOnChangeComplete({
min: min,
max: max
});
}
handleMaxChange = (evt) => {
const min = this.state.minValue;
const max = parseFloat(evt.target.value);
if (isNaN(max)) {
if (min === '') {
this.setState({
minValue: '',
isMinValid: true,
maxValue: '',
isMaxValid: true,
errorMsgs: [],
});
return;
}
this.setState({
maxValue: '',
isMaxValid: false,
errorMsgs: ['both min and max must be set'],
});
return;
} else if (max < min) {
this.setState({
maxValue: max,
isMaxValid: false,
errorMsgs: ['max must be greater than min'],
});
return;
}
let min;
let max;
if (inputValue < otherValue) {
min = inputValue;
max = otherValue;
} else {
min = otherValue;
max = inputValue;
}
this.handleOnChangeComplete({
min: min,
max: max
@ -81,44 +135,53 @@ export class RangeControl extends Component {
renderControl() {
return (
<div>
<input
id={`${this.props.control.id}_min`}
disabled={!this.props.control.isEnabled()}
name="min"
type="number"
className="kuiTextInput"
value={this.state.minValue}
min={this.props.control.min}
max={this.props.control.max}
onChange={this.handleInputChange}
/>
<div className="inputRangeContainer">
<InputRange
disabled={!this.props.control.isEnabled()}
maxValue={this.props.control.max}
minValue={this.props.control.min}
step={this.props.control.options.step}
value={this.state.sliderValue}
onChange={this.handleOnChange}
onChangeComplete={this.handleOnChangeComplete}
draggableTrack={true}
ariaLabelledby={this.props.control.id}
formatLabel={this.formatLabel}
/>
</div>
<input
id={`${this.props.control.id}_max`}
disabled={!this.props.control.isEnabled()}
name="max"
type="number"
className="kuiTextInput"
value={this.state.maxValue}
min={this.props.control.min}
max={this.props.control.max}
onChange={this.handleInputChange}
/>
</div>
<EuiFormRow
isInvalid={!this.state.isMinValid || !this.state.isMaxValid}
error={this.state.errorMsgs}
>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<input
id={`${this.props.control.id}_min`}
disabled={!this.props.control.isEnabled()}
name="min"
type="number"
className="euiFieldNumber"
value={this.state.minValue}
min={this.props.control.min}
max={this.props.control.max}
onChange={this.handleMinChange}
/>
</EuiFlexItem>
<EuiFlexItem className="inputRangeContainer">
<InputRange
disabled={!this.props.control.isEnabled()}
maxValue={this.props.control.max}
minValue={this.props.control.min}
step={this.props.control.options.step}
value={this.state.sliderValue}
onChange={this.handleOnChange}
onChangeComplete={this.handleOnChangeComplete}
draggableTrack={true}
ariaLabelledby={this.props.control.id}
formatLabel={this.formatLabel}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<input
id={`${this.props.control.id}_max`}
disabled={!this.props.control.isEnabled()}
name="max"
type="number"
className="euiFieldNumber"
value={this.state.maxValue}
min={this.props.control.min}
max={this.props.control.max}
onChange={this.handleMaxChange}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFormRow>
);
}

View file

@ -6,7 +6,7 @@
.inputRangeContainer {
display: inline-block;
width: 70%;
margin: 30px 0 0 0;
}
input.kuiTextInput {
@ -30,10 +30,6 @@
.input-range__label-container {
left: 0% !important;
}
.actions {
margin-top: 5px;
}
}
visualization.input_control_vis {

View file

@ -184,10 +184,6 @@
> .vis-edit-sidebar-buttons {
flex: 0 0 auto;
}
label {
margin-bottom: 0px;
}
}
}

View file

@ -18,20 +18,22 @@
opacity: 0.35;
}
.Select-control {
background-color: #fff;
border-radius: 4px;
border: 1px solid #DEDEDE;
color: #191E23;
background: #fbfbfb;
color: #3F3F3F;
cursor: default;
display: table;
border-spacing: 0;
border-collapse: separate;
height: 36px;
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;

View file

@ -4,6 +4,7 @@ export default function ({ getService, getPageObjects }) {
const retry = getService('retry');
const find = getService('find');
const remote = getService('remote');
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['dashboard', 'header', 'common']);
describe('dashboard grid', () => {
@ -66,7 +67,7 @@ export default function ({ getService, getPageObjects }) {
.releaseMouseButton();
await retry.try(async () => {
const controls = await find.allByCssSelector('.inputControlVis .kuiFlexItem');
const controls = await testSubjects.findAll('inputControlItem');
expect(controls.length).to.equal(3);
const control0Position = await controls[0].getPosition();
const control1Position = await controls[1].getPosition();
@ -86,7 +87,7 @@ export default function ({ getService, getPageObjects }) {
.releaseMouseButton();
await retry.try(async () => {
const controls = await find.allByCssSelector('.inputControlVis .kuiFlexItem');
const controls = await testSubjects.findAll('inputControlItem');
expect(controls.length).to.equal(3);
const control0Position = await controls[0].getPosition();
const control1Position = await controls[1].getPosition();
@ -98,7 +99,7 @@ export default function ({ getService, getPageObjects }) {
});
it('Should position controls inside panel', async () => {
const controls = await find.allByCssSelector('.inputControlVis .kuiFlexItem');
const controls = await testSubjects.findAll('inputControlItem');
expect(controls.length).to.equal(3);
const control0Size = await controls[0].getSize();
const control1Size = await controls[1].getSize();