feat(live-preview): support blocks with relationships inside richtext lexical for client side preview
What?
This PR adds support for blocks with relationships inside richtext lexical for client side preview. Currently blocks are filled with the data that is available, but relationships are not resolved and filled. This is causing missing relationship data in those blocks in client side live preview of richtext.
Before
After
How?
Inside payload package:
- I added richtext blocks definition to clientconfig, I could not see this exported to client side anywhere else. I'm not sure if this is the best way to extract or expose this info, so would like feedback on this.
- Also added blocks info to richText field in fieldSchemaToJSON so it's usable by live preview.
Inside live-preview package:
- In the traversal of richtext, hook in so that it uses traverseFields for the blocks. Using the config that was exposed above. I'm a bit unsure about the block itself where I just added the version and type, so would like feedback on this.
Inside test live-preview:
- Just hooks up the MediaBlock to the lexicalEditor and the serializer for it.
Fixes #5285
@GermanJablo Thanks for looking into this. I fixed the build errors after the merged and tested it manually. Still working.
I created #12167 to try to prepare for integration tests of this feature. Maybe it should be merged into this PR and then work on the tests here?
Thanks to you @andershermansen. This is a challenging issue!
Inside payload package:
- I added richtext blocks definition to clientconfig, I could not see this exported to client side anywhere else. I'm not sure if this is the best way to extract or expose this info, so would like feedback on this.
- Also added blocks info to richText field in fieldSchemaToJSON so it's usable by live preview.
Inside live-preview package:
- In the traversal of richtext, hook in so that it uses traverseFields for the blocks. Using the config that was exposed above. I'm a bit unsure about the block itself where I just added the version and type, so would like feedback on this.
We can be sure that the serialized blocks are already being passed to the client somehow, since they're used there. After investigating, I found this is happening with BlocksFeature, which passes the serialized blocks to BlocksFeatureClient. If we also pass the blocks to RichTextFieldClient, as you're doing now, we'd be duplicating the content that the server has to process and send to the client. How to get the serialized blocks on the client requires further investigation. We probably have a provider that does that. From what I've been seeing, it might be useEditorConfigContext or FeatureProviderClient.
I created https://github.com/payloadcms/payload/pull/12167 to try to prepare for integration tests of this feature. Maybe it should be merged into this PR and then work on the tests here?
I'll review that PR shortly to get a better answer.
@GermanJablo I merged in latest main and added an integration test. It does not pass as the result in the fields is undefined. It still works when running dev, but not in integration test. Have not yet investigated why. I just thought it was good to add that integration test anyway.
Were you able to read my previous comment? There's a problem with the PR approach.
Were you able to read my previous comment? There's a problem with the PR approach.
I read it, but I do not fully understand it. Need to read up more on the code you referenced and debug more to understand how it works.
As I wrote in the initial comment on this PR this was not code ready to merge, as I was very unsure on how to do this. So appreciate your feedback so far and will look more into it.
Ok! If it helps, a simpler tldr:
BlocksFeature already sends the serialized blocks to the client.
We need to find a way to access them on the client without sending them again from somewhere else.
@GermanJablo I took another approach in the latest push in this PR. I used the global blocks config and converted that to a blocksMap, it's sent it once same way as the full fields definition (fieldSchemaJSON) is sent. This way the richtext traverser can use all global defined blocks introduced in #10905
This PR then solves this for blocks defined in global blocks and used in lexical, but not blocks defined directly in the BlocksFeature. That is at least better than current situation. Please have a look and let me know what you think.
Thanks again. Solving the problem for global blocks is a step forward.
Yay :smile:
My hypothesis is that the generic solution should use
featureClientSchemaMap(passed inuseEditorConfigContext), although I don't know how prop drilling would work here, since neither theuinorlive-previewpackages haverichtext-lexicalas dependencies. Were you able to explore anything aboutfeatureClientSchemaMap? It seems to have information for every block in every editor.
featureClientSchemaMap has the information needed yes. You can see it's used here to create a map like the one we need:
https://github.com/payloadcms/payload/blob/36fd6e905a002b203c9e7e9202f57db4dc5dddad/packages/richtext-lexical/src/features/blocks/client/index.tsx#L48-L56
But what you are mentioning is what I do not know how to solve. How to connect the dot's between the featureClientSchemaMap and the LivePreviewWindow which needs it.
We're exploring a different way to solve this here: https://github.com/payloadcms/payload/pull/13619
Manually traversing and populating fields like this is only a short-term solution and will be a pain to maintain. This approach still has holes, e.g. custom link drawer fields won't be populated. Any additional functionality we add in the future which requires population would also require us to adjust this live-preview code - we'd be playing whack-a-mole.
We already handle populating relationships correctly, for all our fields including richtext - this happens in the findByID operation where we run hooks.
The idea behind the new approach is to use that existing endpoint to correctly populate our data. That way the population is faster (1 single request), and we can get rid of all custom code required to populate data on the client. Additionally, this allows us to support running hooks within live preview. This means the lexicalHTMLField will now be supported in client-side live preview!
Closing in favor of #13619. Thanks a lot for the effort put in here @andershermansen !