remove binds from render functions

This commit is contained in:
Nathan Reese 2017-09-13 11:11:46 -06:00
parent 645be65780
commit 7465606331
7 changed files with 204 additions and 173 deletions

View file

@ -4,7 +4,6 @@ exports[`renders ControlsTab 1`] = `
<div>
<ControlEditor
controlIndex={0}
controlLabel="custom label"
controlParams={
Object {
"fieldName": "keywordField",
@ -20,40 +19,18 @@ exports[`renders ControlsTab 1`] = `
"type": "list",
}
}
controlTitle="list: custom label"
getIndexPattern={[Function]}
getIndexPatterns={[Function]}
handleCheckboxOptionChange={[Function]}
handleFieldNameChange={[Function]}
handleIndexPatternChange={[Function]}
handleLabelChange={[Function]}
handleNumberOptionChange={[Function]}
handleRemoveControl={[Function]}
moveDownControl={[Function]}
moveUpControl={[Function]}
>
<ListControlEditor
controlIndex={0}
controlParams={
Object {
"fieldName": "keywordField",
"id": "1",
"indexPattern": "indexPattern1",
"label": "custom label",
"options": Object {
"multiselect": true,
"order": "desc",
"size": 5,
"type": "terms",
},
"type": "list",
}
}
getIndexPattern={[Function]}
getIndexPatterns={[Function]}
handleFieldNameChange={[Function]}
handleIndexPatternChange={[Function]}
handleMultiselectChange={[Function]}
handleSizeChange={[Function]}
/>
</ControlEditor>
moveControl={[Function]}
/>
<ControlEditor
controlIndex={1}
controlLabel=""
controlParams={
Object {
"fieldName": "numberField",
@ -66,34 +43,16 @@ exports[`renders ControlsTab 1`] = `
"type": "range",
}
}
controlTitle="range: numberField"
getIndexPattern={[Function]}
getIndexPatterns={[Function]}
handleCheckboxOptionChange={[Function]}
handleFieldNameChange={[Function]}
handleIndexPatternChange={[Function]}
handleLabelChange={[Function]}
handleNumberOptionChange={[Function]}
handleRemoveControl={[Function]}
moveDownControl={[Function]}
moveUpControl={[Function]}
>
<RangeControlEditor
controlIndex={1}
controlParams={
Object {
"fieldName": "numberField",
"id": "2",
"indexPattern": "indexPattern1",
"label": "",
"options": Object {
"step": 1,
},
"type": "range",
}
}
getIndexPattern={[Function]}
getIndexPatterns={[Function]}
handleDecimalPlacesChange={[Function]}
handleFieldNameChange={[Function]}
handleIndexPatternChange={[Function]}
handleStepChange={[Function]}
/>
</ControlEditor>
moveControl={[Function]}
/>
<div
className="kuiSideBarFormRow"
>

View file

@ -1,6 +1,9 @@
import classNames from 'classnames';
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';
export class ControlEditor extends Component {
@ -14,7 +17,64 @@ export class ControlEditor extends Component {
));
}
changeLabel = (evt) => {
this.props.handleLabelChange(this.props.controlIndex, evt);
}
removeControl = () => {
this.props.handleRemoveControl(this.props.controlIndex);
}
moveUpControl = () => {
this.props.moveControl(this.props.controlIndex, -1);
}
moveDownControl = () => {
this.props.moveControl(this.props.controlIndex, 1);
}
changeIndexPattern = (evt) => {
this.props.handleIndexPatternChange(this.props.controlIndex, evt);
}
changeFieldName = (evt) => {
this.props.handleFieldNameChange(this.props.controlIndex, evt);
}
renderEditor() {
let controlEditor = null;
switch (this.props.controlParams.type) {
case 'list':
controlEditor = (
<ListControlEditor
controlIndex={this.props.controlIndex}
controlParams={this.props.controlParams}
handleIndexPatternChange={this.changeIndexPattern}
handleFieldNameChange={this.changeFieldName}
getIndexPatterns={this.props.getIndexPatterns}
getIndexPattern={this.props.getIndexPattern}
handleNumberOptionChange={this.props.handleNumberOptionChange}
handleCheckboxOptionChange={this.props.handleCheckboxOptionChange}
/>
);
break;
case 'range':
controlEditor = (
<RangeControlEditor
controlIndex={this.props.controlIndex}
controlParams={this.props.controlParams}
handleIndexPatternChange={this.changeIndexPattern}
handleFieldNameChange={this.changeFieldName}
getIndexPatterns={this.props.getIndexPatterns}
getIndexPattern={this.props.getIndexPattern}
handleNumberOptionChange={this.props.handleNumberOptionChange}
/>
);
break;
default:
throw new Error(`Unhandled control editor type ${this.props.controlParams.type}`);
}
const labelId = `controlLabel${this.props.controlIndex}`;
return (
<div>
@ -27,13 +87,13 @@ export class ControlEditor extends Component {
className="kuiTextInput"
id={labelId}
type="text"
value={this.props.controlLabel}
onChange={this.props.handleLabelChange}
value={this.props.controlParams.label}
onChange={this.changeLabel}
/>
</div>
</div>
{this.props.children}
{controlEditor}
</div>
);
}
@ -56,14 +116,14 @@ export class ControlEditor extends Component {
<i aria-hidden="true" className={visibilityToggleClasses} />
</button>
<span className="vis-editor-agg-header-title ng-binding">
{this.props.controlTitle}
{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.props.moveDownControl}
onClick={this.moveDownControl}
data-test-subj={`inputControlEditorMoveDownControl${this.props.controlIndex}`}
>
<i aria-hidden="true" className="fa fa-chevron-down" />
@ -72,7 +132,7 @@ export class ControlEditor extends Component {
aria-label="Move control up"
type="button"
className="kuiButton kuiButton--small"
onClick={this.props.moveUpControl}
onClick={this.moveUpControl}
data-test-subj={`inputControlEditorMoveUpControl${this.props.controlIndex}`}
>
<i aria-hidden="true" className="fa fa-chevron-up" />
@ -81,7 +141,7 @@ export class ControlEditor extends Component {
aria-label="Remove control"
className="kuiButton kuiButton--danger kuiButton--small"
type="button"
onClick={this.props.handleRemoveControl}
onClick={this.removeControl}
data-test-subj={`inputControlEditorRemoveControl${this.props.controlIndex}`}
>
<i aria-hidden="true" className="fa fa-times" />
@ -97,11 +157,14 @@ export class ControlEditor extends Component {
ControlEditor.propTypes = {
controlIndex: PropTypes.number.isRequired,
controlLabel: PropTypes.string.isRequired,
controlTitle: PropTypes.string.isRequired,
controlParams: PropTypes.object.isRequired,
handleLabelChange: PropTypes.func.isRequired,
moveUpControl: PropTypes.func.isRequired,
moveDownControl: PropTypes.func.isRequired,
moveControl: PropTypes.func.isRequired,
handleRemoveControl: PropTypes.func.isRequired,
children: PropTypes.node.isRequired
handleIndexPatternChange: PropTypes.func.isRequired,
handleFieldNameChange: PropTypes.func.isRequired,
getIndexPatterns: PropTypes.func.isRequired,
getIndexPattern: PropTypes.func.isRequired,
handleCheckboxOptionChange: PropTypes.func.isRequired,
handleNumberOptionChange: PropTypes.func.isRequired
};

View file

@ -2,25 +2,16 @@ import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { ControlEditor } from './control_editor';
import { RangeControlEditor } from './range_control_editor';
import { ListControlEditor } from './list_control_editor';
import { KuiButton, KuiButtonIcon } from 'ui_framework/components';
import { addControl, getTitle, moveControl, newControl, removeControl, setControl } from '../../editor_utils';
import { addControl, moveControl, newControl, removeControl, setControl } from '../../editor_utils';
export class ControlsTab extends Component {
constructor(props) {
super(props);
this.state = {
type: 'list'
};
this.getIndexPatterns = this.getIndexPatterns.bind(this);
this.getIndexPattern = this.getIndexPattern.bind(this);
this.handleAddControl = this.handleAddControl.bind(this);
state = {
type: 'list'
}
async getIndexPatterns(search) {
getIndexPatterns = async (search) => {
const resp = await this.props.scope.vis.API.savedObjectsClient.find({
type: 'index-pattern',
fields: ['title'],
@ -31,7 +22,7 @@ export class ControlsTab extends Component {
return resp.savedObjects;
}
async getIndexPattern(indexPatternId) {
getIndexPattern = async (indexPatternId) => {
return await this.props.scope.vis.API.indexPatterns.get(indexPatternId);
}
@ -41,98 +32,67 @@ export class ControlsTab extends Component {
this.props.stageEditorParams(params);
}
handleLabelChange(controlIndex, evt) {
handleLabelChange = (controlIndex, evt) => {
const updatedControl = this.props.scope.vis.params.controls[controlIndex];
updatedControl.label = evt.target.value;
this.setVisParam('controls', setControl(this.props.scope.vis.params.controls, controlIndex, updatedControl));
}
handleIndexPatternChange(controlIndex, evt) {
handleIndexPatternChange = (controlIndex, evt) => {
const updatedControl = this.props.scope.vis.params.controls[controlIndex];
updatedControl.indexPattern = evt.value;
updatedControl.fieldName = '';
this.setVisParam('controls', setControl(this.props.scope.vis.params.controls, controlIndex, updatedControl));
}
handleFieldNameChange(controlIndex, evt) {
handleFieldNameChange = (controlIndex, evt) => {
const updatedControl = this.props.scope.vis.params.controls[controlIndex];
updatedControl.fieldName = evt.value;
this.setVisParam('controls', setControl(this.props.scope.vis.params.controls, controlIndex, updatedControl));
}
handleCheckboxOptionChange(controlIndex, optionName, evt) {
handleCheckboxOptionChange = (controlIndex, optionName, evt) => {
const updatedControl = this.props.scope.vis.params.controls[controlIndex];
updatedControl.options[optionName] = evt.target.checked;
this.setVisParam('controls', setControl(this.props.scope.vis.params.controls, controlIndex, updatedControl));
}
handleNumberOptionChange(controlIndex, optionName, evt) {
handleNumberOptionChange = (controlIndex, optionName, evt) => {
const updatedControl = this.props.scope.vis.params.controls[controlIndex];
updatedControl.options[optionName] = parseFloat(evt.target.value);
this.setVisParam('controls', setControl(this.props.scope.vis.params.controls, controlIndex, updatedControl));
}
handleRemoveControl(controlIndex) {
handleRemoveControl = (controlIndex) => {
this.setVisParam('controls', removeControl(this.props.scope.vis.params.controls, controlIndex));
}
moveControl(controlIndex, direction) {
moveControl = (controlIndex, direction) => {
this.setVisParam('controls', moveControl(this.props.scope.vis.params.controls, controlIndex, direction));
}
handleAddControl() {
handleAddControl = () => {
this.setVisParam('controls', addControl(this.props.scope.vis.params.controls, newControl(this.state.type)));
}
renderControls() {
return this.props.scope.vis.params.controls.map((controlParams, controlIndex) => {
let controlEditor = null;
switch (controlParams.type) {
case 'list':
controlEditor = (
<ListControlEditor
controlIndex={controlIndex}
controlParams={controlParams}
handleIndexPatternChange={this.handleIndexPatternChange.bind(this, controlIndex)}
handleFieldNameChange={this.handleFieldNameChange.bind(this, controlIndex)}
getIndexPatterns={this.getIndexPatterns}
getIndexPattern={this.getIndexPattern}
handleMultiselectChange={this.handleCheckboxOptionChange.bind(this, controlIndex, 'multiselect')}
handleSizeChange={this.handleNumberOptionChange.bind(this, controlIndex, 'size')}
/>
);
break;
case 'range':
controlEditor = (
<RangeControlEditor
controlIndex={controlIndex}
controlParams={controlParams}
handleIndexPatternChange={this.handleIndexPatternChange.bind(this, controlIndex)}
handleFieldNameChange={this.handleFieldNameChange.bind(this, controlIndex)}
getIndexPatterns={this.getIndexPatterns}
getIndexPattern={this.getIndexPattern}
handleDecimalPlacesChange={this.handleNumberOptionChange.bind(this, controlIndex, 'decimalPlaces')}
handleStepChange={this.handleNumberOptionChange.bind(this, controlIndex, 'step')}
/>
);
break;
default:
throw new Error(`Unhandled control editor type ${controlParams.type}`);
}
return (
<ControlEditor
key={controlParams.id}
controlIndex={controlIndex}
controlLabel={controlParams.label}
controlTitle={getTitle(controlParams, controlIndex)}
controlParams={controlParams}
handleLabelChange={this.handleLabelChange.bind(this, controlIndex)}
moveUpControl={this.moveControl.bind(this, controlIndex, -1)}
moveDownControl={this.moveControl.bind(this, controlIndex, 1)}
handleRemoveControl={this.handleRemoveControl.bind(this, controlIndex)}
>
{controlEditor}
</ControlEditor>
handleLabelChange={this.handleLabelChange}
moveControl={this.moveControl}
handleRemoveControl={this.handleRemoveControl}
handleIndexPatternChange={this.handleIndexPatternChange}
handleFieldNameChange={this.handleFieldNameChange}
getIndexPatterns={this.getIndexPatterns}
getIndexPattern={this.getIndexPattern}
handleCheckboxOptionChange={this.handleCheckboxOptionChange}
handleNumberOptionChange={this.handleNumberOptionChange}
/>
);
});
}

View file

@ -10,6 +10,13 @@ function filterField(field) {
export function ListControlEditor(props) {
const multiselectId = `multiselect-${props.controlIndex}`;
const sizeId = `size-${props.controlIndex}`;
const handleMultiselectChange = (evt) => {
props.handleCheckboxOptionChange(props.controlIndex, 'multiselect', evt);
};
const handleSizeChange = (evt) => {
props.handleNumberOptionChange(props.controlIndex, 'size', evt);
};
return (
<div>
@ -37,7 +44,7 @@ export function ListControlEditor(props) {
className="kuiCheckBox"
type="checkbox"
checked={props.controlParams.options.multiselect}
onChange={props.handleMultiselectChange}
onChange={handleMultiselectChange}
/>
</div>
</div>
@ -53,7 +60,7 @@ export function ListControlEditor(props) {
type="number"
min="1"
value={props.controlParams.options.size}
onChange={props.handleSizeChange}
onChange={handleSizeChange}
/>
</div>
</div>
@ -69,6 +76,6 @@ ListControlEditor.propTypes = {
controlParams: PropTypes.object.isRequired,
handleFieldNameChange: PropTypes.func.isRequired,
handleIndexPatternChange: PropTypes.func.isRequired,
handleMultiselectChange: PropTypes.func.isRequired,
handleSizeChange: PropTypes.func.isRequired
handleCheckboxOptionChange: PropTypes.func.isRequired,
handleNumberOptionChange: PropTypes.func.isRequired
};

View file

@ -57,14 +57,14 @@ const controlParams = {
};
let handleFieldNameChange;
let handleIndexPatternChange;
let handleMultiselectChange;
let handleSizeChange;
let handleCheckboxOptionChange;
let handleNumberOptionChange;
beforeEach(() => {
handleFieldNameChange = sinon.spy();
handleIndexPatternChange = sinon.spy();
handleMultiselectChange = sinon.spy();
handleSizeChange = sinon.spy();
handleCheckboxOptionChange = sinon.spy();
handleNumberOptionChange = sinon.spy();
});
test('renders ListControlEditor', () => {
@ -75,13 +75,13 @@ test('renders ListControlEditor', () => {
controlParams={controlParams}
handleFieldNameChange={handleFieldNameChange}
handleIndexPatternChange={handleIndexPatternChange}
handleMultiselectChange={handleMultiselectChange}
handleSizeChange={handleSizeChange}
handleCheckboxOptionChange={handleCheckboxOptionChange}
handleNumberOptionChange={handleNumberOptionChange}
/>);
expect(component).toMatchSnapshot(); // eslint-disable-line
});
test('handleMultiselectChange', () => {
test('handleCheckboxOptionChange - multiselect', () => {
const component = mount(<ListControlEditor
getIndexPatterns={getIndexPatterns}
getIndexPattern={getIndexPattern}
@ -89,18 +89,29 @@ test('handleMultiselectChange', () => {
controlParams={controlParams}
handleFieldNameChange={handleFieldNameChange}
handleIndexPatternChange={handleIndexPatternChange}
handleMultiselectChange={handleMultiselectChange}
handleSizeChange={handleSizeChange}
handleCheckboxOptionChange={handleCheckboxOptionChange}
handleNumberOptionChange={handleNumberOptionChange}
/>);
const checkbox = component.find('#multiselect-0');
checkbox.simulate('change', { target: { checked: true } });
sinon.assert.calledOnce(handleMultiselectChange);
sinon.assert.notCalled(handleFieldNameChange);
sinon.assert.notCalled(handleIndexPatternChange);
sinon.assert.notCalled(handleSizeChange);
sinon.assert.notCalled(handleNumberOptionChange);
const expectedControlIndex = 0;
const expectedOptionName = 'multiselect';
sinon.assert.calledWith(
handleCheckboxOptionChange,
expectedControlIndex,
expectedOptionName,
sinon.match((evt) => {
if (evt.target.checked === true) {
return true;
}
return false;
}, 'unexpected checkbox input event'));
});
test('handleSizeChange', () => {
test('handleNumberOptionChange - size', () => {
const component = mount(<ListControlEditor
getIndexPatterns={getIndexPatterns}
getIndexPattern={getIndexPattern}
@ -108,13 +119,24 @@ test('handleSizeChange', () => {
controlParams={controlParams}
handleFieldNameChange={handleFieldNameChange}
handleIndexPatternChange={handleIndexPatternChange}
handleMultiselectChange={handleMultiselectChange}
handleSizeChange={handleSizeChange}
handleCheckboxOptionChange={handleCheckboxOptionChange}
handleNumberOptionChange={handleNumberOptionChange}
/>);
const input = component.find('#size-0');
input.simulate('change', { target: { value: 7 } });
sinon.assert.notCalled(handleMultiselectChange);
sinon.assert.notCalled(handleCheckboxOptionChange);
sinon.assert.notCalled(handleFieldNameChange);
sinon.assert.notCalled(handleIndexPatternChange);
sinon.assert.calledOnce(handleSizeChange);
const expectedControlIndex = 0;
const expectedOptionName = 'size';
sinon.assert.calledWith(
handleNumberOptionChange,
expectedControlIndex,
expectedOptionName,
sinon.match((evt) => {
if (evt.target.value === 7) {
return true;
}
return false;
}, 'unexpected input event'));
});

View file

@ -10,6 +10,12 @@ function filterField(field) {
export function RangeControlEditor(props) {
const stepSizeId = `stepSize-${props.controlIndex}`;
const decimalPlacesId = `decimalPlaces-${props.controlIndex}`;
const handleDecimalPlacesChange = (evt) => {
props.handleNumberOptionChange(props.controlIndex, 'decimalPlaces', evt);
};
const handleStepChange = (evt) => {
props.handleNumberOptionChange(props.controlIndex, 'step', evt);
};
return (
<div>
@ -37,7 +43,7 @@ export function RangeControlEditor(props) {
className="kuiTextInput"
type="number"
value={props.controlParams.options.step}
onChange={props.handleStepChange}
onChange={handleStepChange}
/>
</div>
</div>
@ -53,7 +59,7 @@ export function RangeControlEditor(props) {
type="number"
min="0"
value={props.controlParams.options.decimalPlaces}
onChange={props.handleDecimalPlacesChange}
onChange={handleDecimalPlacesChange}
/>
</div>
</div>
@ -69,6 +75,5 @@ RangeControlEditor.propTypes = {
controlParams: PropTypes.object.isRequired,
handleFieldNameChange: PropTypes.func.isRequired,
handleIndexPatternChange: PropTypes.func.isRequired,
handleDecimalPlacesChange: PropTypes.func.isRequired,
handleStepChange: PropTypes.func.isRequired
handleNumberOptionChange: PropTypes.func.isRequired
};

View file

@ -56,14 +56,12 @@ const controlParams = {
};
let handleFieldNameChange;
let handleIndexPatternChange;
let handleStepChange;
let handleDecimalPlacesChange;
let handleNumberOptionChange;
beforeEach(() => {
handleFieldNameChange = sinon.spy();
handleIndexPatternChange = sinon.spy();
handleStepChange = sinon.spy();
handleDecimalPlacesChange = sinon.spy();
handleNumberOptionChange = sinon.spy();
});
test('renders RangeControlEditor', () => {
@ -74,13 +72,12 @@ test('renders RangeControlEditor', () => {
controlParams={controlParams}
handleFieldNameChange={handleFieldNameChange}
handleIndexPatternChange={handleIndexPatternChange}
handleStepChange={handleStepChange}
handleDecimalPlacesChange={handleDecimalPlacesChange}
handleNumberOptionChange={handleNumberOptionChange}
/>);
expect(component).toMatchSnapshot(); // eslint-disable-line
});
test('handleStepChange', () => {
test('handleNumberOptionChange - step', () => {
const component = mount(<RangeControlEditor
getIndexPatterns={getIndexPatterns}
getIndexPattern={getIndexPattern}
@ -88,18 +85,27 @@ test('handleStepChange', () => {
controlParams={controlParams}
handleFieldNameChange={handleFieldNameChange}
handleIndexPatternChange={handleIndexPatternChange}
handleStepChange={handleStepChange}
handleDecimalPlacesChange={handleDecimalPlacesChange}
handleNumberOptionChange={handleNumberOptionChange}
/>);
const input = component.find('#stepSize-0');
input.simulate('change', { target: { value: 0.5 } });
sinon.assert.calledOnce(handleStepChange);
sinon.assert.notCalled(handleFieldNameChange);
sinon.assert.notCalled(handleIndexPatternChange);
sinon.assert.notCalled(handleDecimalPlacesChange);
const expectedControlIndex = 0;
const expectedOptionName = 'step';
sinon.assert.calledWith(
handleNumberOptionChange,
expectedControlIndex,
expectedOptionName,
sinon.match((evt) => {
if (evt.target.value === 0.5) {
return true;
}
return false;
}, 'unexpected input event'));
});
test('handleDecimalPlacesChange', () => {
test('handleNumberOptionChange - decimalPlaces', () => {
const component = mount(<RangeControlEditor
getIndexPatterns={getIndexPatterns}
getIndexPattern={getIndexPattern}
@ -107,13 +113,22 @@ test('handleDecimalPlacesChange', () => {
controlParams={controlParams}
handleFieldNameChange={handleFieldNameChange}
handleIndexPatternChange={handleIndexPatternChange}
handleStepChange={handleStepChange}
handleDecimalPlacesChange={handleDecimalPlacesChange}
handleNumberOptionChange={handleNumberOptionChange}
/>);
const input = component.find('#decimalPlaces-0');
input.simulate('change', { target: { value: 2 } });
sinon.assert.notCalled(handleStepChange);
sinon.assert.notCalled(handleFieldNameChange);
sinon.assert.notCalled(handleIndexPatternChange);
sinon.assert.calledOnce(handleDecimalPlacesChange);
const expectedControlIndex = 0;
const expectedOptionName = 'decimalPlaces';
sinon.assert.calledWith(
handleNumberOptionChange,
expectedControlIndex,
expectedOptionName,
sinon.match((evt) => {
if (evt.target.value === 2) {
return true;
}
return false;
}, 'unexpected input event'));
});