- Issue created by @bnjmnm
- ๐บ๐ธUnited States bnjmnm Ann Arbor, MI
Full page without toolbar etc. The XB Content area slot works like it should. IDK if we should do more within this issue scope or just get this in so it's easier to try out different page editing approaches.
- First commit to issue fork.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
wim leers โ made their first commit to this issueโs fork.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Looks great!
E2E tests pass, which means this does work.
The only test that fails is
\Drupal\Tests\experience_builder\Kernel\ApiPreviewControllerTest
, and that fails because it directly tests the controller, which now no longer returns aJsonResponse
, but a render array. The transformation to a JSON response object now happens in that new main content renderer ๐The new base test class that ๐ Adding or editing a Page brings user into Experience Builder not entity form Active adds introduces the infra that would allow
ApiPreviewControllerTest
to largely remain unchanged.I suggest cherry-picking that base class into this MR โ whichever one lands first introduces the infra, the other MR will be able to become simpler ๐
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
This blocks ๐ Add support for global regions Active .
- ๐บ๐ธUnited States bnjmnm Ann Arbor, MI
Seems fine to switch the response to HTML. I know error handling was one of the concerns mentioned in Slack, but JS error checking/reporting is still captured and displayed properly in the try/catch and the preview itself has Drupal message regions which makes it extra capable at error reporting.
- ๐ซ๐ฎFinland lauriii Finland
FYI, I opened ๐ Improve server-side error handling Active to improve the error handling. I don't think we should render the error message in the rendered preview but instead there should be a specific interface in XB that handles them. It sounds like the JSON to HTML change might make that more challenging.
- ๐ฌ๐งUnited Kingdom longwave UK
longwave โ changed the visibility of the branch 3489302-preview-entire-page to hidden.
- ๐ณ๐ฑNetherlands balintbrews Amsterdam, NL
I would like to propose that we reconsider switching to HTML as the response format and stick to JSON.
As @lauriii mentioned in #11 ๐ Preview entire page not just content area Active , error messages shouldn't appear as part of the preview. This is in line with our aspiration to keep the rendered preview as intact as we can, so it truly represents what end users will see.
In order to handle errors outside of the preview, we do need them in a JSON response. @longwave's suggestion to set the
responseHandler
option tocontent-type
for the endpoint generated by RTK Query would solve this elegantly: the response would be parsed according to theContent-Type
header from the response, so it's possible to mix HTML and JSON responses.While that is certainly a solution, I'm concerned that RTK Query's abstraction hides the fact that we would be creating an unusually complex client requirement. Our implementation happens to solve it easily through an abstraction, and while I don't pretend to foresee that there will be other clients consuming this API endpoint, it's probably a good idea not to rule that out, even just for the sake of designing a better API.
I think it's overall a better API design to keep a consistent response format.
What is the problem that we're trying to solve with switching to HTML response? Debugging was mentioned on Slack. What would be the exact scenario?
- ๐ฌ๐งUnited Kingdom f.mazeikis Brighton
f.mazeikis โ made their first commit to this issueโs fork.
- ๐บ๐ธUnited States bnjmnm Ann Arbor, MI
Other people on this issue are making compelling arguments to go back to the JSON response. I switched it out yesterday because I thought it effectively preserved the error handling but it looks like that isn't the case. The motivation wasn't that strong, tbh and not opposed to switching back.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
#13 + #15: could an alternative be to:
- always send a HTML response
- โฆ but in case of an error due to an invalid component tree (typically in the inputs, so props for an
SDC
-sourced Component, settings for aBlock
-sourced Component), make the status code of the response422: Unprocessable Content
(and probably an empty response body, but this is less important) - โฆ and in case of plain failure (e.g. incorrect logic in a block plugin, partially failed code deployment โฆ), make the status code of the response
500
. - update the client to verify the response status code is
200
, and for anything else, provide a fallback UX as @lauriii described in ๐ Improve server-side error handling Active
(For point 3: I described in detail in #3485878-7: Component previews should NEVER be able to render PHP errors, should fall back to a meaningful error instead โ how literally any error at any point during the preview rendering could be guaranteed to be caught to ensure a great UX in XB.)
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
We should improve the error handling so that errors that happen during API requests, never end up in the preview.
โ @lauriii at #3485878-6: Component previews should NEVER be able to render PHP errors, should fall back to a meaningful error instead โ
๐ This is why I'm not sure we even need any error details for previews specifically, unlike what @balintbrews describes in #13.
- ๐ณ๐ฑNetherlands balintbrews Amsterdam, NL
#19 ๐ Preview entire page not just content area Active :
That quote from @lauriii is what I also expressed in #13 ๐ Preview entire page not just content area Active .
My interpretation is that we don't intend to display errors as part of the generated preview, but that doesn't mean we don't intend to display errors in the XB app somewhere when generating the preview goes wrong. Likely in a toast, as mentioned in ๐ Improve server-side error handling Active .
The question is how granular we would like to be with these errors. If not so much, i.e. we're happy with two different kind of generic errors, then #17 ๐ Preview entire page not just content area Active works! I guess many other scenarios can be expressed with HTTP codes, so this can even scale to more errors.
I will say, I don't get why we are putting so much emphasis on this when have a system worked out for JSON responses with error handling, already implemented, used by many other endpoints. I'm probably failing to understand some benefit of this potential change. ๐
- ๐ฌ๐งUnited Kingdom longwave UK
The only real argument is that the response is a full HTML page and nothing more, and HTTP already allows us to return this trivially by setting the Content-Type header.
We can still return error details in JSON if we need to. One thing I'm not sure how to handle yet: if there are warnings during preview, but not errors that prevent rendering, where and how should they be surfaced?
- ๐ซ๐ฎFinland lauriii Finland
Warnings should also be displayed outside the preview. We could render them in a toast or a similar component.
- ๐ฌ๐งUnited Kingdom longwave UK
In which case if we can have both HTML response *and* warnings, we need to represent it via JSON.
- ๐ซ๐ฎFinland lauriii Finland
It looks like the XB preview is now showing global regions but the actual main content is slightly different between the real site and XB. Is there still an additional step needed to render the node content using the display mode? FWIW, if this is difficult to do, it would be fine to handle this in a follow-up issue.
XB:
Actual page:
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
#26:
That's because this MR is not rendering the main content block
\Drupal\system\Plugin\Block\SystemMainBlock
. This MR pretends the component tree for the currentNode
orPage
is the main content, and then lets that "main content" be decorated by blocks โ i.e. it still usesBlockPageVariant
.This is good enough for the
Page
entity introduced by ๐ฑ [Research] Landing page integration Active , because\Drupal\experience_builder\Entity\PageViewBuilder::alterBuild()
only renders the component tree.For
Node
(and other content entities, and actually when editing thePageTemplate
and looking at an arbitrary route), we need to reuse the original route (for editing a content entity that'd be its$content_entity->toUrl('canonical')
route/link template) but replace/override/intercept the route parameter with one that reflects the values in the XB UI of the XB field (the component tree) and all other fields.- For content entities being edited through XB that means calling the controller with an
EntityInterface
object with all field values dynamically overridden compared to the saved (published) values. (ForNode
:\Drupal\node\Controller\NodeViewController::view()
with aNodeInterface
object.) - For arbitrary routes viewed in XB (to edit the regions for the active theme's
PageTemplate
โ see ๐ Add support for global regions Active ), we don't need to do anything: it'd just be pass-through.
I think updating
ApiPreviewController
for that is indeed out-of-scope here. I thinkApiPreviewController must use the previewed route's controller, and override canonical content entity routes' received entity object
is an accurate albeit long issue title. ๐ค ๐ - For content entities being edited through XB that means calling the controller with an
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
The changes this MR makes are simple and focused. #26 is out-of-scope here, and #28 provides an outline of how that could work. Let's create a new issue for that, with #28 as the initial implementation proposal.
This MR allows the
PageTemplate
functionality that ๐ Introduce an XB `PageTemplate` config entity Active introduced to become visible in previews in the XB UI! ๐Why?
As soon as a
PageTemplate
config entity is created for the default theme, as of this MR, the preview will use the component trees stored in thePageTemplate
config entity, becauseApiPreviewController
no longer callsBareHtmlPageRenderer
. Instead, it returns a render array ("the main content for the controller"), and lets the default Drupal page rendering process handle wrapping that main content render array into a full page. By default, that isBlockPageVariant
. And once aPageTemplate
config entity exists, it'll be\Drupal\experience_builder\Plugin\DisplayVariant\PageTemplateDisplayVariant
.If you're interested in how that works, see
\Drupal\Tests\experience_builder\Functional\PageTemplateVariantTest::test()
.The next step is to actually start creating/populating a
PageTemplate
config entity. That's what ๐ Add support for global regions Active is for, which this blocks. - ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Turns out #28 pre-emptively answered most of what @longwave raised in #3489899-8: [PP-1] Add support for global regions โ ! ๐
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Hm โฆ perhaps the E2E test failures are legitimate? ๐ค Last full green CI pipeline was Nov 26. ๐ Adapt E2E tests to work with auto-save Active landed Nov 27. I bet that's where the root cause lies, somewhereโฆ ๐
- First commit to issue fork.
-
lauriii โ
committed 15875cd3 on 0.x authored by
bnjmnm โ
Issue #3489302 by longwave, bnjmnm, jessebaker, wim leers, f.mazeikis,...
-
lauriii โ
committed 15875cd3 on 0.x authored by
bnjmnm โ
- ๐ซ๐ฎFinland lauriii Finland
The UI + OpenAPI changes are minimal and @jessebaker and @wim leers have been active here so going ahead and merging this.
- ๐บ๐ธUnited States mglaman WI, USA
This copied \Drupal\Tests\experience_builder\Kernel\ExperienceBuilderTestBase and broke any test using it when dependencies are installed due to how \Drupal\Tests\experience_builder\TestSite\XBTestSetup operates.
- ๐ฌ๐งUnited Kingdom longwave UK
@mglaman what's broken exactly? Wim asked for the test base to be copied over in #6.
- ๐บ๐ธUnited States mglaman WI, USA
Because you cannot add dependencies to be installed on the base test. The test this issue added runs the site setup install script, which manually installs modules. It assumes a non-kernel test environment.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
I suggest cherry-picking that base class into this MR โ whichever one lands first introduces the infra, the other MR will be able to become simpler ๐
โ me in #6
Of course, that assumed that there would not be any changes made to the base class, and changes were made. So it's a bit more complicated now.
This MR updated
ApiPreviewControllerTest
like so:- class ApiPreviewControllerTest extends KernelTestBase { + final class ApiPreviewControllerTest extends ExperienceBuilderTestBase {
โฆ but the
(new XBTestSetup())->setup();
line was already present in the test, @mglaman.
I do agree that is a bit atypical (calling another class'
:setup()
method from a test's::setUp()
), but it doesn't seem impossible for ๐ Adding or editing a Page brings user into Experience Builder not entity form Active to overcome? ๐ค - ๐บ๐ธUnited States mglaman WI, USA
I have to completely rewrite ApiPreviewControllerTest due to its usage of XBTestSetup. Unless we skip defining dependencies in the test base class, which is completely useless. Perhaps it should have all gone into a trait as I was wondering in my MR.
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
- ๐ง๐ชBelgium wim leers Ghent ๐ง๐ช๐ช๐บ
Created the missing follow-up: ๐ [later phase] ApiPreviewController must use the previewed route's controller, and override canonical content entity routes' received entity object Postponed . Based on @lauriii in #26 and yours truly in #28.
Automatically closed - issue fixed for 2 weeks with no activity.