Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace gridster with react-grid-layout #13853

Merged

Conversation

stacey-gammon
Copy link
Contributor

@stacey-gammon stacey-gammon commented Sep 5, 2017

Replaces gridster with react-grid-layout and and reactifies the dashboard panels and headers.

Makes some UI changes that are nearer inline with k7:
screen shot 2017-09-19 at 12 47 06 pm

Also allows moving the panel on the entire panel header, no longer just on a move icon, which has been something requested for awhile (#7927)

As for placing panels, I had to manually come up with an algorithm to find the best spot because the default that react-grid-layout gives isn't great, and doesn't match prior functionality. It will find the first spot that fits the new panel with first the lowest y value then the lowest x.

@stacey-gammon stacey-gammon added Feature:Dashboard Dashboard related features :Sharing labels Sep 5, 2017
@stacey-gammon stacey-gammon force-pushed the react/replace-dashboard-grid branch 6 times, most recently from 98f72bc to e3925d1 Compare September 8, 2017 20:50
@stacey-gammon stacey-gammon force-pushed the react/replace-dashboard-grid branch 14 times, most recently from 7c7923f to 8571931 Compare September 18, 2017 14:31
@stacey-gammon
Copy link
Contributor Author

s3 upload error

Jenkins, test this

@stacey-gammon stacey-gammon force-pushed the react/replace-dashboard-grid branch 3 times, most recently from b794cf5 to ac601d9 Compare September 19, 2017 14:51
@stacey-gammon
Copy link
Contributor Author

s3 error again, technically all the tests passed.

@stacey-gammon stacey-gammon changed the title [WIP] Replace gridster with react-grid-layout Replace gridster with react-grid-layout Sep 19, 2017
Copy link
Contributor

@kobelb kobelb left a comment

Choose a reason for hiding this comment

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

This is great work, all of the additional tests are just great.

The following error is being logged in the Browser console:

warning.js:36 Warning: Failed prop type: The prop `onPanelUpdated` is marked as required in `DashboardGrid`, but its value is `undefined`.
    in DashboardGrid

angular.js:14642 TypeError: onPanelUpdated is not a function
    at dashboard_grid.js:103
    at Array.forEach (<anonymous>)
    at Object.DashboardGrid._this.onLayoutChange (dashboard_grid.js:91)
    at ReactGridLayout.onLayoutMaybeChanged (ReactGridLayout.js:204)
    at ReactGridLayout.componentDidMount (ReactGridLayout.js:66)
    at ReactCompositeComponent.js:264
    at measureLifeCyclePerf (ReactCompositeComponent.js:75)
    at ReactCompositeComponent.js:263
    at CallbackQueue.notifyAll (CallbackQueue.js:76)
    at ReactReconcileTransaction.close (ReactReconcileTransaction.js:80)

Apparently unrelated, the batched requests that courier does are behaving weirdly on master and I'm seeing 2 _msearch calls for a dashboard with 2 of the same visualization. I noticed the behavior initially with this PR and thought that the asynchronous manner that we were called this.embeddableHandler.render was the culprit, but the behavior is present before these changes. Definitely something we should keep an eye on, to ensure this PR doesn't have any impact as well.


this.containerApi = getContainerApi();
this.embeddableHandler = getEmbeddableHandler(panel.type);
const editUrl = await this.embeddableHandler.getEditPath(panel.id);
Copy link
Contributor

@kobelb kobelb Sep 22, 2017

Choose a reason for hiding this comment

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

If we were to change this code to:

this.embeddableHandler.getEditPath(panel.id).then(editUrl => this.setState({ editUrl }));
this.embeddableHandler.getTitleFor(panel.id).then(title => this.setState({ title }));

it'd be roughly in-line with the first "not a warning" case outline here, with the sole difference being they're using callbacks instead of Promise.

Even with Redux, we'll still be using actions to queue off async actions in ComponentDidMount, but the updated data will be coming through via our props as opposed to the state.

/* eslint-disable react/no-did-mount-set-state */
this.setState({ editUrl, title });

this.destroyEmbeddable = await this.embeddableHandler.render(
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we waiting for the title/editUrl to be available before calling this.embeddableHandler.render they don't seem to be dependent on each other? If we did the above suggestion, and queued off this async request immediately, I'm not seeing the reason for us to track the _isMounted, but we could just use the this.destroyEmbeddable !== null) check directly in the componentDidUnmount call.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I need isMounted check before the setStates or I can get:
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the DashboardPanel component.

I can still use your above suggestion but I don't think I can get rid of isMounted. Instead it will look like this:

    this.embeddableHandler.getEditPath(panel.id).then(editUrl => {
      if (this._isMounted) { this.setState({ editUrl }); }
    });

    /* eslint-disable react/no-did-mount-set-state */
    this.embeddableHandler.getTitleFor(panel.id).then(title => {
      if (this._isMounted) { this.setState({ title }); }
    });

    this.destroyEmbeddable = await this.embeddableHandler.render(
      this.panelElement,
      panel,
      this.containerApi);

fwiw, the redux variation gets rid of all this. I actually changed this.embeddableHandler.render to return an Embeddable, which contains state for the rendered embeddable, including title and editUrl - so there is only one async call, not three - https://github.com/elastic/kibana/pull/14103/files#diff-a18d16d17e2c646a166a4d5523608fbfR86/

Why are we waiting for the title/editUrl to be available before calling this.embeddableHandler.render

Wasn't intentional, I just liked the await syntax. Updated to your suggestion.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, gotcha. Pretty excited about the redux changes coming, that makes sense.

Code from the redux PR snuck into this one.
@stacey-gammon
Copy link
Contributor Author

@kobelb -Good catch on the onUpdatedPanel warning. That code was actually part of the Redux PR that snuck in. I reverted it back.

I filed an issue for the msearch concerns so that can be looked into separately: #14128

@kobelb
Copy link
Contributor

kobelb commented Sep 22, 2017

All my concerns have been addressed, once CI goes green you'll have my LGTM!

@stacey-gammon
Copy link
Contributor Author

stacey-gammon commented Sep 23, 2017

I discovered an issue with the panels being unmounted/mounted too frequently and causing slow dashboard refreshes on edit/view mode change, due to this bug: react-grid-layout/react-grid-layout#240.

Found another bug where the grid was being rendered with width 0, then not rerendered, showing all the panels shoved to one side.

Copy link
Contributor

@nreese nreese left a comment

Choose a reason for hiding this comment

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

LGTM

@stacey-gammon stacey-gammon merged commit e35d7b0 into elastic:master Sep 26, 2017
stacey-gammon added a commit to stacey-gammon/kibana that referenced this pull request Oct 2, 2017
* Initial check-in to replace gridster with react-grid-layout and reactify panels

* # This is a combination of 3 commits.
# This is the 1st commit message:
Add margin of error to test determining panel widths

# This is the commit message #2:

use real kibana version when creating panel data. Will make future conversions easier.

# This is the commit message #3:

Fix lint errors

* Add margin of error to test determining panel widths

use real kibana version when creating panel data. Will make future conversions easier.

Move default height and width to dashboard_constants so those that need it don't end up including extra stuff like ui/chrome

* Remove unnecessary _.once when creating react directives in dashboard.js

* Remove unnecessary constructors

* Use componentDidMount instead of componentWillMount bc of async calls, and handle case where destroyEmbeddable is not defined.

* Remove unnecessary null in classNames

* Use loads defaultsDeep instead of Object.assign

* use render* instead of get* for functions returning an element

* use relative css paths

* Use local import path

* Switch to local imports and remove need for plugins path in jest tests

* Improve accessibility of max/min panel toggle icon

* remove unused css

Had to implement this via code

* disable eslint rule for setState in componentDidMount

Am not aware of a better way to handle this, aside from switching to
redux, since it’s recommended not to put async calls in
componentWillMount.  Since I plan to investigate redux next, disabling
for now. Open to other’s opinions on the matter.

* Use native map instead of lodash

* Have the grid handle setting the z-indexes of the right reactgriditem

* Make the draggable handle the title, not the whole heading

Otherwise the drag event often takes over click events when trying to
open the panel options menu and it gets really annoying.

* Change from click to mouse down detector in KuiOutsideClickDector so drags also close pop ups.

* Fix mistaken commit

Code from the redux PR snuck into this one.

* Run getEditPath and getTitle async calls in parallel - no need to wait on the return value of one before starting the others.

* Fix tests: update snapshots, add promise returns.

* version being added to panelData in the wrong spot caused isDirty flag to be true when it shouldn't be

* Fix unmounting/mounting problem with panels due to view/edit mode switch

* Fix bug where panels get squashed to one side when view mode is changed while a panel is expanded.

* Update snapshots to match wrong view mode comparison

* Improve naming of a variable

* Fix issue with pop over hiding behind tile maps

* Previous panel.js included ui/doc_table and ui/visualize - needed to include them in the chain for Dash only mode but not in that file.

* Fix bad merge: remove baseline screenshots
stacey-gammon added a commit that referenced this pull request Oct 2, 2017
* Initial check-in to replace gridster with react-grid-layout and reactify panels

* # This is a combination of 3 commits.
# This is the 1st commit message:
Add margin of error to test determining panel widths

# This is the commit message #2:

use real kibana version when creating panel data. Will make future conversions easier.

# This is the commit message #3:

Fix lint errors

* Add margin of error to test determining panel widths

use real kibana version when creating panel data. Will make future conversions easier.

Move default height and width to dashboard_constants so those that need it don't end up including extra stuff like ui/chrome

* Remove unnecessary _.once when creating react directives in dashboard.js

* Remove unnecessary constructors

* Use componentDidMount instead of componentWillMount bc of async calls, and handle case where destroyEmbeddable is not defined.

* Remove unnecessary null in classNames

* Use loads defaultsDeep instead of Object.assign

* use render* instead of get* for functions returning an element

* use relative css paths

* Use local import path

* Switch to local imports and remove need for plugins path in jest tests

* Improve accessibility of max/min panel toggle icon

* remove unused css

Had to implement this via code

* disable eslint rule for setState in componentDidMount

Am not aware of a better way to handle this, aside from switching to
redux, since it’s recommended not to put async calls in
componentWillMount.  Since I plan to investigate redux next, disabling
for now. Open to other’s opinions on the matter.

* Use native map instead of lodash

* Have the grid handle setting the z-indexes of the right reactgriditem

* Make the draggable handle the title, not the whole heading

Otherwise the drag event often takes over click events when trying to
open the panel options menu and it gets really annoying.

* Change from click to mouse down detector in KuiOutsideClickDector so drags also close pop ups.

* Fix mistaken commit

Code from the redux PR snuck into this one.

* Run getEditPath and getTitle async calls in parallel - no need to wait on the return value of one before starting the others.

* Fix tests: update snapshots, add promise returns.

* version being added to panelData in the wrong spot caused isDirty flag to be true when it shouldn't be

* Fix unmounting/mounting problem with panels due to view/edit mode switch

* Fix bug where panels get squashed to one side when view mode is changed while a panel is expanded.

* Update snapshots to match wrong view mode comparison

* Improve naming of a variable

* Fix issue with pop over hiding behind tile maps

* Previous panel.js included ui/doc_table and ui/visualize - needed to include them in the chain for Dash only mode but not in that file.

* Fix bad merge: remove baseline screenshots
@stacey-gammon stacey-gammon deleted the react/replace-dashboard-grid branch October 24, 2017 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants