Skip to content

Provide InputRange component valid value when Range slider is not set.#20002

Merged
nreese merged 12 commits intoelastic:masterfrom
nreese:issue-19803-take2
Jul 12, 2018
Merged

Provide InputRange component valid value when Range slider is not set.#20002
nreese merged 12 commits intoelastic:masterfrom
nreese:issue-19803-take2

Conversation

@nreese
Copy link
Copy Markdown
Contributor

@nreese nreese commented Jun 18, 2018

fixes #19803

Move all unset logic out of control class and into react component where it is used.

@elasticmachine
Copy link
Copy Markdown
Contributor

💔 Build Failed

@nreese nreese force-pushed the issue-19803-take2 branch from 39ac194 to 5243155 Compare June 18, 2018 18:26
@elasticmachine
Copy link
Copy Markdown
Contributor

💔 Build Failed

@nreese
Copy link
Copy Markdown
Contributor Author

nreese commented Jun 18, 2018

Looks like CI problems caused test failures because ES could not start

info  [o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main]
18:40:31    │       org.elasticsearch.bootstrap.StartupException: BindHttpException[Failed to bind to [9220]]; nested: BindException[Address already in use];

jenkins, test this

@elasticmachine
Copy link
Copy Markdown
Contributor

💔 Build Failed

@nreese
Copy link
Copy Markdown
Contributor Author

nreese commented Jun 18, 2018

20:04:43          └- ✖ fail: "dashboard app using legacy data dashboard listing page delete default confirm action is cancel"
20:04:43          │        Error: expected true to equal false
20:04:43          │         at Assertion.assert (node_modules/expect.js/index.js:96:13)
20:04:43          │         at Assertion.be.Assertion.equal (node_modules/expect.js/index.js:216:10)
20:04:43          │         at Assertion.(anonymous function) [as be] (node_modules/expect.js/index.js:69:24)
20:04:43          │         at Context.<anonymous> (test/functional/apps/dashboard/_dashboard_listing.js:56:49)
20:04:43          │         at <anonymous>:null:null
20:04:43          │         at process._tickCallback (internal/process/next_tick.js:188:7)

jenkins, test this

@elasticmachine
Copy link
Copy Markdown
Contributor

💔 Build Failed

@nreese nreese force-pushed the issue-19803-take2 branch from 5243155 to aa8ad70 Compare June 18, 2018 22:23
@elasticmachine
Copy link
Copy Markdown
Contributor

💔 Build Failed

@nreese nreese force-pushed the issue-19803-take2 branch from aa8ad70 to e595b6c Compare June 19, 2018 12:25
@elasticmachine
Copy link
Copy Markdown
Contributor

💔 Build Failed

@nreese
Copy link
Copy Markdown
Contributor Author

nreese commented Jun 19, 2018

jenkins, test this

@elasticmachine
Copy link
Copy Markdown
Contributor

💚 Build Succeeded

let newValue = selectedOptions;
if (selectedOptions.length === 0) {
// control is empty
newValue = undefined;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of passing in undefined here, what about just passing in selectedOptions, as it was before, but having list_control.js (the business logic, not the component) override hasValue to check for an empty array, (or undefined too perhaps). Feels like this component having to understand what stageFilter would count as empty or not is leaking too much internal knowledge.

@@ -115,7 +113,7 @@ export class Control {
}

clear() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add comments to explain the difference between reset and clear? It makes more sense when I see the UI but looking only at the code it's not obvious.

Also, clear indiscriminately changes _hasChanged to be true which can create some inconsistencies in a UX experience:

inputcontrolshasvalue


const toState = (props) => {
let sliderValue = props.control.value;
if (!props.control.value) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be using hasValue as the check? Also looks like this function only uses props.control so no need to pass in the entire props.

Copy link
Copy Markdown
Contributor

@chrisdavies chrisdavies left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM w/ the caveat that I agree w/ Stacey's comments. Nothing to add on top of those.

@elasticmachine
Copy link
Copy Markdown
Contributor

💔 Build Failed

@nreese
Copy link
Copy Markdown
Contributor Author

nreese commented Jun 25, 2018

jenkins, test this

@elasticmachine
Copy link
Copy Markdown
Contributor

💚 Build Succeeded

@nreese
Copy link
Copy Markdown
Contributor Author

nreese commented Jun 27, 2018

@stacey-gammon this is ready for another look

}
const state = {
sliderValue: props.control.value,
sliderValue: sliderValue,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can be shortened to just sliderValue (https://github.com/airbnb/javascript#es6-object-concise)

min: control.min,
max: control.min
};
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could keep sliderValue as const via:

const sliderValue = control.hasValue() ?
  control.value :
  sliderValue = {
    min: control.min,
    max: control.min
  };

state.maxValue = props.control.value.max;
if (control.hasValue()) {
state.minValue = control.value.min;
state.maxValue = control.value.max;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could make this a bit more concise via changing above:

...
     minValue: control.hasValue() ? control.value.min : '',
     maxValue: control.hasValue() ? control.value.max : '',
...

*/
clear() {
this.set(this.filterManager.getUnsetValue());
this.set();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo it'd be clearer to do this.value = undefined; Can set ever be called outside of clear with undefined? If not, we could throw an error in set if newValue is not defined (or when we eventually typescript we could tell then we don't support undefined), and then we don't have to check this.hasValue(), just always assume there is a value.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to support value being undefined to signal when the control is unset.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't seem to trigger set being called with undefined outside of this clear function when playing around with the control. Can you tell me the instance you are referring to? Or maybe we are misunderstanding each other. I understand we need to support the value being undefined, I just mean writing the code like this would be clearer imo:

set(newValue) {
  this.value = newValue;
  this._kbnFilter = this.filterManager.createFilter(this.value);
}

clear() {
  this.value = undefined;
  this._kbnFilter = null;
}

Then when this supports typescript we can do something like set(newValue: T) instead of set(newValue: T | undefined)

Copy link
Copy Markdown
Contributor Author

@nreese nreese Jul 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a case where hasValue is needed. In the list control, when the list is cleared, set is called with []. In this case, _kbnFilter needs to be set to null since there is no filter value. This logic could move into filterManager.createFilter if that makes things easier to understand.

}

hasValue() {
return this.value && this.value.length > 0;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is a bug here. Looks like I can't set an input control drop down to false. Should probably be a hard check for undefined. Could you add a test that would have caught this issue when you fix it?

Copy link
Copy Markdown
Contributor Author

@nreese nreese Jul 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value can never be set to false. For list control, the value is either undefined or an array of objects with the shape label and value. I will create a test to show how the value gets set

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay. I suppose I am hitting another bug. I created a list drop down with true and false values for the sample flight data set and I get:

Uncaught (in promise) Error: 0 is not a valid boolean value for boolean field Cancelled
    at getConvertedValueForField (phrase.js:71)
    at buildPhraseFilter (phrase.js:31)
    at PhraseFilterManager.createFilter (phrase_filter_manager.js:72)
    at ListControl.set (control.js:154)
    at VisController._callee3$ (vis_controller.js:190)
    at tryCatch (runtime.js:65)
    at Generator.invoke [as _invoke] (runtime.js:303)
    at Generator.prototype.(anonymous function) [as next] (http://localhost:5601/xmb/bundles/vendors.bundle.js:218445:21)
    at step (vis_controller.js:41)
    at vis_controller.js:41
    at new Promise (<anonymous>)
    at VisController.<anonymous> (vis_controller.js:41)
    at VisController.stageFilter (vis_controller.js:218)
    at ListControl._this.handleOnChange (list_control.js:64)
    at EuiComboBox.onAddOption (combo_box.js:630)
    at onOptionClick (combo_box.js:621)

Once we have this typescripted we can enforce that set on the base class is only ever called with a certain type, but as it is now, it's not clear that set should only be called with an array type or undefined. But I suppose this is fine as is for this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind creating a new issue for using boolean fields?

@elasticmachine
Copy link
Copy Markdown
Contributor

💔 Build Failed

@nreese
Copy link
Copy Markdown
Contributor Author

nreese commented Jul 9, 2018

Test failure in unrelated area.

fail: "visualize app tag cloud chart formatted field should apply filter with unformatted value"
15:40:31    │ proc  [ftr]        │       
15:40:31    │ proc  [ftr]        │         Error: expected [ '30GB', '20GB', '19GB', '18GB', '17GB' ] to sort of equal [ '30GB' ]
15:40:31    │ proc  [ftr]        │         + expected - actual
15:40:31    │ proc  [ftr]        │       
15:40:31    │ proc  [ftr]        │          [
15:40:31    │ proc  [ftr]        │            "30GB"
15:40:31    │ proc  [ftr]        │         -  "20GB"
15:40:31    │ proc  [ftr]        │         -  "19GB"
15:40:31    │ proc  [ftr]        │         -  "18GB"
15:40:31    │ proc  [ftr]        │         -  "17GB"
15:40:31    │ proc  [ftr]        │          ]
15:40:31    │ proc  [ftr]        │         
15:40:31    │ proc  [ftr]        │         at Assertion.assert (node_modules/expect.js/index.js:96:13)
15:40:31    │ proc  [ftr]        │         at Assertion.eql (node_modules/expect.js/index.js:230:10)
15:40:31    │ proc  [ftr]        │         at Context.<anonymous> (test/functional/apps/visualize/_tag_cloud.js:173:25)
15:40:31    │ proc  [ftr]        │         at <anonymous>
15:40:31    │ proc  [ftr]        │         at process._tickCallback (internal/process/next_tick.js:188:7)

jenkins, test this

@elasticmachine
Copy link
Copy Markdown
Contributor

💔 Build Failed

@nreese
Copy link
Copy Markdown
Contributor Author

nreese commented Jul 9, 2018

another unrelated test error

fail: "visualize app tag cloud chart formatted field "before all" hook for "should show correct data""
16:56:22    │ proc  [ftr]        │        tryForTime timeout: Error: tryForTime timeout: [POST http://localhost:9515/session/a2abecb06e7af49e4321fcec8a4d7b2a/element / {"using":"css selector","value":"[href=\"#/visualize\"]"}] no such element: Unable to locate element: {"method":"css selector","selector":"[href="#/visualize"]"}

jenkins, test this

@elasticmachine
Copy link
Copy Markdown
Contributor

💚 Build Succeeded

@elasticmachine
Copy link
Copy Markdown
Contributor

💚 Build Succeeded

Copy link
Copy Markdown

@stacey-gammon stacey-gammon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Latest review was code only, pulled locally and tested on the prior commit.

@nreese nreese merged commit c8ffb05 into elastic:master Jul 12, 2018
nreese added a commit to nreese/kibana that referenced this pull request Jul 12, 2018
elastic#20002)

* move unsetLogic into react component

* remove extra comment

* add comment about why empty state is needed for InputRange component

* fix broken jest test

* move empty state logic from react component to ListControl class, add comments about reset and clear functions

* add comments about clear and reset to control class

* calculate hasChanged to avoid bug where clear form still shows 'cancel changes' as active for an empty form

* use hasValue in range control to check if value exists

* add unit test for list_control_factory and cleanup range_control from review comments
nreese added a commit that referenced this pull request Jul 12, 2018
#20002) (#20735)

* move unsetLogic into react component

* remove extra comment

* add comment about why empty state is needed for InputRange component

* fix broken jest test

* move empty state logic from react component to ListControl class, add comments about reset and clear functions

* add comments about clear and reset to control class

* calculate hasChanged to avoid bug where clear form still shows 'cancel changes' as active for an empty form

* use hasValue in range control to check if value exists

* add unit test for list_control_factory and cleanup range_control from review comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failed prop type: "value" must be in between "minValue" and "maxValue"

4 participants