-
Notifications
You must be signed in to change notification settings - Fork 8.2k
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
[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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
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 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 didn't set a title in the example app, fixed this
valueInput: input, | ||
}, | ||
}); | ||
}, |
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 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we expecting that other plugins will start depending on Lens in the plugin system?
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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: |
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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_example
Consumer 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) => void
Takes 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.tsx
contains the example plugin using these APIsInternals
x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_component.tsx
andx-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_component_loader.tsx
provide a very thin wrapper around the embeddable acting as a lazy-loading mini embeddable container, passing through the input via props.navigateToPrefilledEditor
simply usesEmbeddableStateTransfer
to kick off the navigation like the edit action on dashboard does.Normally the
attributes
of 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
originatingAppId
optionalExtensions