[Lens] Implement deep linking and embedding#84416
Conversation
|
@elasticmachine merge upstream |
|
@elasticmachine merge upstream |
| "requiredPlugins": [ | ||
| "lens", | ||
| "data", | ||
| "developerExamples" |
There was a problem hiding this comment.
Hey @flash1293! For this example plugin, can we add a dependency on features to illustrate that you'll need to grant access to the lens saved object type in order to properly embed when security is enabled?
I'm happy to help draft this change if you'd like help with it
There was a problem hiding this comment.
@legrego Happy to include this - but I'm not sure how it should look like.
This example is not working with saved objects directly, but it does link into the Lens editor. So I guess the right integration would be to check whether there there are at least visualize read permissions via ui capabilities and otherwise disable the button, right?
There was a problem hiding this comment.
This example is not working with saved objects directly, but it does link into the Lens editor. So I guess the right integration would be to check whether there there are at least visualize read permissions via ui capabilities and otherwise disable the button, right?
Ah, so this doesn't allow you to view existing visualizations, or save new ones? If that's the case, then you shouldn't need any capabilities checks
There was a problem hiding this comment.
As discussed offline, I will introduce a third method on the contract which can be used by consumers to determine whether it's possible to link to Lens or not.
|
Jenkins, test this |
|
Pinging @elastic/kibana-app (Team:KibanaApp) |
|
@elasticmachine merge upstream |
wylieconlon
left a comment
There was a problem hiding this comment.
I'm going to do a second pass on this, but left some questions for you.
| to: 'now', | ||
| }, | ||
| attributes: getLensAttributes( | ||
| props.core.uiSettings.get('defaultIndex'), |
There was a problem hiding this comment.
So I ran into this by coincidence, but the @timestamp field isn't available on the ecommerce data, which causes the example to crash. Maybe the example should be tied to a specific index like logs?
There was a problem hiding this comment.
Good point, I fixed this by reading the index pattern and using the default time field
| <EuiButton | ||
| isDisabled={!props.plugins.lens.canUseEditor()} | ||
| onClick={() => { | ||
| props.plugins.lens.navigateToPrefilledEditor({ |
There was a problem hiding this comment.
I didn't set a title in the example app, fixed this
| valueInput: input, | ||
| }, | ||
| }); | ||
| }, |
There was a problem hiding this comment.
I think that this pre-filled editor logic is not quite right. First of all the breadcrumbs are not set. Second of all: are we expecting that users will return to the app they came from, or that the saved Lens visualization will get added to a dashboard? Right now it suggests adding to a dashboard.
There was a problem hiding this comment.
Yes, this was intended. It's possible to have a channel back to the app (using the originating app parameter), but that's much more complex to implement correctly because the app has to somehow persist the current state, then restore it.
IMHO this is a separate feature we can work on separately once it becomes relevant - I think the flow "solution app -> Lens -> dashboard" is what makes sense here (because solution apps don't want to provide a way to persist/load custom Lens visualizations).
This is similar to how the metrics explorer integration with TSVB works right now.
| EuiTitle, | ||
| } from '@elastic/eui'; | ||
| import { CoreStart } from 'kibana/public'; | ||
| import { TypedLensByValueInput } from '../../../plugins/lens/public'; |
There was a problem hiding this comment.
Are we expecting that other plugins will start depending on Lens in the plugin system?
There was a problem hiding this comment.
Yes, exactly - as they are creating Lens-specific configuration, this seems like a good way to represent it on the type level
| name: 'indexpattern-datasource-layer-layer1', | ||
| type: 'index-pattern', | ||
| }, | ||
| ], |
There was a problem hiding this comment.
I'm a bit worried about the references parameter of our saved object. Seems easy for an app to provide the wrong information.
There was a problem hiding this comment.
I thought about a builder function of some sort abstracting away these things, but didn't want to overdo it for the first experimental release.
Do you have something simple in mind we could add here? IMHO we can wait for consumers to see in which direction we should drive this API.
There was a problem hiding this comment.
I was also expecting some kind of builder, but I agree that we should iterate on it. For now I'm assuming that users will copy+paste the JSON from a saved object.
💚 Build SucceededMetrics [docs]Module Count
Async chunks
Page load bundle
History
To update your PR or re-run it, just comment with: |
wylieconlon
left a comment
There was a problem hiding this comment.
Okay I think you're right that we can iterate on this, but this seems like a useful first step. Tested and LGTM.
| name: 'indexpattern-datasource-layer-layer1', | ||
| type: 'index-pattern', | ||
| }, | ||
| ], |
There was a problem hiding this comment.
I was also expecting some kind of builder, but I agree that we should iterate on it. For now I'm assuming that users will copy+paste the JSON from a saved object.


This PR explores ways to implement deep linking and embedding in Lens.
It includes a small example application which embedds a config inlined in the consuming app with two buttons to randomly change the color of the chart and another one to take the current configuration and make it editable in Lens.
To test:
yarn start --run-examples/app/embedded_lens_exampleConsumer side
This PR adds two things to the lens start contract:
EmbeddableComponent: React.ComponentType<LensProps>A component usable in your application which takes either a persisted state of a Lens visualization (technically it's the embeddable input, but there's very little difference) or a saved object id of a Lens visualization. The component loads the Lens bundle and uses the Lens embeddable implementation to render the visualization very similar to how it's working in a dashboard. If the input changes, the visualization is rendered again.navigateToPrefilledEditor: (input: LensEmbeddableInput) => voidTakes a Lens embeddable input (again persisted state or saved object id) and navigates to Lens with this state preloadedLensProps['attributes']is properly typed for the individual state shapes, so it's possible to statically check consumers of this API.x-pack/examples/embedded_lens_example/public/app.tsxcontains the example plugin using these APIsInternals
x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_component.tsxandx-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_component_loader.tsxprovide a very thin wrapper around the embeddable acting as a lazy-loading mini embeddable container, passing through the input via props.navigateToPrefilledEditorsimply usesEmbeddableStateTransferto kick off the navigation like the edit action on dashboard does.Normally the
attributesof the Lens embeddable input are typed very loose, this PR makes them specific for all existing visualizations:Once we make it possible to register visualizations from outside of the Lens plugin, we can use an approach similar to UI actions to extend a central interface containing all existing pairs to keep this level of type-safety.
Problems
originatingAppIdoptionalExtensions