-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Portable Dashboards] Prep Redux Tools #136572
[Portable Dashboards] Prep Redux Tools #136572
Conversation
💚 CLA has been signed |
…ing on Control Group
…e slider, and control group
2f5e805
to
ffa8253
Compare
…eDashboard/prepReduxWrapper
…eDashboard/prepReduxWrapper
Pinging @elastic/kibana-presentation (Team:Presentation) |
@elasticmachine merge upstream |
…eDashboard/prepReduxWrapper
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wooo, so happy this is going in 🎉
Mostly a code review only... I did pull and run Kibana, added some controls to Dashboard and ensured everything still... worked? Honestly not sure what else to do, since there's no user-facing changes, heh :) But nothing exploded, so woohoo!
Left a few questions/comments but nothing major. I think it all makes sense to me, and I'm excited for when this can finally be used in Dashboard - seeing it used for Controls really shows the potential!
super( | ||
initialInput, | ||
{ embeddableLoaded: {} }, | ||
{ dataViewIds: [], loading: false, embeddableLoaded: {}, filters: [] }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... Why is loading
false here? Are you just letting the parent constructor take care of it? If so, why set it explicitly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not actually sure why I added that - I think at one point I might have modified the output type more significantly, but the Control group doesn't even use loading. It actually has it's own untilReady
method that does the same thing. Will remove this.
const { isInputEqual: inputEqualityCheck, isOutputEqual: outputEqualityCheck } = settings ?? {}; | ||
const inputEqual = ( | ||
inputA: Partial<ReduxEmbeddableStateType['explicitInput']>, | ||
inputB: Partial<ReduxEmbeddableStateType['explicitInput']> | ||
) => (inputEqualityCheck ? inputEqualityCheck(inputA, inputB) : deepEqual(inputA, inputB)); | ||
const outputEqual = ( | ||
outputA: ReduxEmbeddableStateType['output'], | ||
outputB: ReduxEmbeddableStateType['output'] | ||
) => (outputEqualityCheck ? outputEqualityCheck(outputA, outputB) : deepEqual(outputA, outputB)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohhhh man, this logic is so much nicer for when we switch Dashboard over to use this for state management 🔥
const { explicitInput: reduxExplicitInput } = store.getState(); | ||
|
||
// store only explicit input in the store | ||
const embeddableExplictiInput = embeddable.getExplicitInput() as Writeable< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo:
const embeddableExplictiInput = embeddable.getExplicitInput() as Writeable< | |
const embeddableExplicitInput = embeddable.getExplicitInput() as Writeable< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, will fix! Nice catch
import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; | ||
import { ControlInput } from '../common/types'; | ||
import { ControlsService } from './services/controls'; | ||
|
||
export interface CommonControlOutput { | ||
filters?: Filter[]; | ||
dataViews?: DataView[]; | ||
dataViewId?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the switch to dataViewId
rather than just dataView
directly? Just for... initial speed perhaps, since it's only needed when changes are actually made to the control's selections?
As far as why it's no longer an array - I assume that's because a control can only have a single data view? Just wanted to clarify :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually a little bit of an awkward change introduced by this PR. Basically embeddables have this pattern where they communicate the data views they use to the Dashboard so that the dashboard can pick appropriate data views when creating a filter. The problem with this is that the data view they were communicating was a whole data view object instance which is non-serializable and cannot be stored in Redux. For this reason I made the switch for Controls only to communicate the data view Id instead.
See this issue for a description of how we could better extend this pattern to other embeddables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh that makes perfect sense - thank you! I definitely think reducing the amount of times we have to fetch the data view objects would be a huge win for performance, so communicating IDs and only fetching when absolutely necessary is a great pattern 💪
invalidSelections={invalidSelections} | ||
updateSearchString={updateSearchString} | ||
/> | ||
<OptionsListPopover width={dimensions.width} updateSearchString={updateSearchString} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So much cleaner, wow 🎉
export const RangeSliderComponent = () => { | ||
return <RangeSliderPopover />; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... Is it worth even keeping RangeSliderComponent
at this point now that a bunch of logic has been removed? Could we not just use RangeSliderPopover
component directly for the embeddable render?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was actually going to work through this with @cqliu1 yeah! The it seems like the whole Component
was just a wrapper for passing some props down (which is no longer needed!). Other than that, I'd really like to be able to split the Popover
up into two components - one with the popover contents only, and then the component can handle everything else, kinda like how Options List does it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created this issue
💚 Build Succeeded
Metrics [docs]Module Count
Public APIs missing comments
Async chunks
Canvas Sharable Runtime
Public APIs missing exports
Page load bundle
Unknown metric groupsAPI count
async chunk count
ESLint disabled line counts
Total ESLint disabled count
History
To update your PR or re-run it, just comment with: |
* Created new Redux system for embeddables in Presentation Util. Migrated all Controls to use it. (cherry picked from commit 01fc584)
💚 All backports created successfully
Note: Successful backport PRs will be merged automatically after passing CI. Questions ?Please refer to the Backport tool documentation |
Summary
Fixes #133681.
This PR introduces a new Redux Embeddable Tools system to enhance embeddable DX for the Portable Dashboards initiative.
This PR:
This PR also migrates the Controls plugin to use the new Redux Embeddable Tools, and removes all other state management workarounds from them.
In addition, this PR reduces the number of re-renders that the Controls are subjected to by using
useSelector
hooks individually for each piece of state that the component needs rather than using one selector for the whole state object.Architecture
Checklist
Delete any items that are not applicable to this PR.