- Issue created by @effulgentsia
- 🇺🇸United States effulgentsia
I think the initial idea for a single
page_template
was when we envisioned it as replacingpage.html.twig
entirely. Meaning, you wouldn't have the concept of theme-determined regions within XB, just a single canvas that you can lay out however you want. But since the UX evolved into being based around theme-determined regions, I think that's a fairly strong argument in favor of refactoring the config entity to match. - 🇫🇮Finland lauriii Finland
Does it worsen DX of config deployments (e.g., doing a manual code review across per-region YAML files vs within a single YAML file)?
My gut feeling is that this isn't significantly worsened at least in the case of a single page template. The impact would be more in the case of multiple page templates. It seems like a trade-off that could be accepted.
Or on the other hand, would it add useful capabilities like creating variants for some regions while leaving other regions shared across page variants?
This could actually be a benefit because for example the header and footer might remain the same on every page template but the content top might need to change for some pages.
I'm wondering if based on this there should be a page template config which can specify a parent page template and is allowed to depend on specific region configurations that would override the parent?
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
🤯 I didn't see this coming for sure. #2 is accurate — that's how @lauriii always described it.
I definitely agree with the cons, especially the variants one. Although @lauriii makes a strong observation in #3.
I'll think about this some more. I urgently need to review some things, leaving not enough time to think through all consequences.
AFAICT this would make 📌 [PP-2] Don't store page template model data in auto-save for an entity Postponed obsolete too, and hence we could add it to the "avoid" list?
- 🇬🇧United Kingdom longwave UK
I don't think this makes 📌 [PP-2] Don't store page template model data in auto-save for an entity Postponed irrelevant, we still store the entire model against all autosaved entities - the aim of that issue is only store the parts of the model that are relevant to each entity.
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
Remember: the future
GlobalPageTemplate
config entity 👻📌 Introduce an XB `PageTemplate` config entity Active introduced the
PageTemplate
config entity (config schema type:type: experience_builder.page_template.*:
). It comes with this comment:# Otherwise, an Experience Builder Page Template can be created per installed theme, and stores component trees for each # region in a theme's `page.html.twig`.
That "otherwise" refers to the preceding config schema type: a placeholder for a future piece of functionality that is very closely related: the global page template config entity.
That looks like so:
# At most a single entity of this type is allowed to exist. If it exists, it *replaces* the theme's `page.html.twig`. experience_builder.global_page_template.*: type: config_entity constraints: FullyValidatable: ~ mapping: # A single component tree. component_tree: # @todo This MUST contain a single XB Component that points to the title block, main content block and messages block # @see \Drupal\Core\Block\MainContentBlockPluginInterface # @see \Drupal\Core\Block\TitleBlockPluginInterface # @see \Drupal\Core\Block\MessagesBlockPluginInterface # @todo Blocked on Blocks-as-XB-Components: https://www.drupal.org/project/experience_builder/issues/3475584 type: experience_builder.component_tree label: 'The component tree that represents the default page'
How would you imagine that to work in the new world proposed by this issue? 🤔 AFAICT, that'd remain unchanged, because it completely ignores the "default/active theme"'s regions.
(Sadly, I can't find any "global page template" details: it's based on discussing this with @laurii IIRC, and is about the "global template" vs the "page template" as captured by https://docs.google.com/spreadsheets/d/1OpETAzprh6DWjpTsZG55LWgldWV_D8jNe9AM73jNaZo/edit?gid=1721130122#gid=1721130122&range=I29">requirements 18 vs 19.)
+1 if we're on the same page
If y'all agree that splitting
PageTemplate
into NPageRegion
config entities does still leave theGlobalPageTemplate
config entity unchanged … then I'm +1 to this proposal, and I do think that it'll make things simpler 😊Bonus! 🚀
In fact, a nice consequence will be that if you try to uninstall a module that provides some SDC or Block, you'd get a more precise overview in the "oops, can't do that, because these config entities depend on it" UI: it'd tell you exactly which regions it's being used in, and in the future even which variants! 🥳
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
To add to #7: that'd also mean that the
content
region would either:- never get a
PageRegion
content entity, because that region is hardcoded (in code) to contain the "main content" block - always get it, but we'd never expose it and it'd be a de facto hardcoded config entity
Related: 🐛 Hide main page content block from XB Active
- never get a
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
- 🇺🇸United States effulgentsia
+1 to doing what the issue title says: changing 1
PageTemplate
config entity per theme into NPageRegion
config entities per theme.I'm confused about what concept
GlobalPageTemplate
represents. If it's meant to be an override ofpage.html.twig
, I think it should be renamed toPageTemplate
(which can be a followup once this issue makes that name available). We'd need to come up with a UI (possibly after 1.0) for how to create/edit this entity. But within this UI, we could make aRegion
component available. Then this would be an exact replacement for page.html.twig (as well as theregions
section of THEME.info.yml). I.e., someone could use this to build a new theme from scratch, including using only the XB UI to create, name, and place regions. - 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
I'm confused about what concept
GlobalPageTemplate
represents. […] should be renamed toPageTemplate
.I think that entire comment captures much more clearly than ever before what @lauriii intended all along! 😄
But it's thanks to the
- 1
PageTemplate
config entity per theme containing data for every region → NPageRegion
config entities per theme, each containing data for 1 region - 1
GlobalPageTemplate
→ 1PageTemplate
rename that you were able to describe it so clearly! 🤩 👏👏
I'd like @lauriii to explicitly confirm to make sure this matches what he envisioned 😊
P.S.: happy to do this one, I think I'm well-positioned to do this system-wide refactor. 🤓
- 1
- 🇫🇮Finland lauriii Finland
#10 and #13 seems like a really solid plan for this. Thank you @effulgentsia and @wim leers 👏
My original thinking last spring was that we would have a single config entity which would store the "page template" meaning the regions available and "block placement" meaning what's inside those regions. We could implement this in phases so that defining the regions is optional and would rely on the theme (to allow integration with existing themes). We've learned since then that this didn't consider all of the factors yet and therefore it was insufficient. I'm +1 to splitting the individual component trees for regions to separate config entities
In my head, global page template is the idea that there would be one template which is the default template (page.html.twig). You could then specify overrides of that for specific parts of the site, e.g. specific content type (page--node--article.html.twig). The latter would be just a regular page template because it's only applied to a specific section of the site. Once we allow multiple page template, it might be clearer to call the global page template the default template at least in code.
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
Adding to #8: 📌 Page title should not be required Active landed too, so the "validation across the component trees for all regions in a given theme" just became simpler.
To recap, there are 3 special kinds of blocks: "main content", "page title" and "messages".
- as of 📌 Page title should not be required Active , the page title no longer gets special treatment — thanks to @lauriii's response to #3505872-5: Page title block should not be required → .
- per #8, the "main content" one no longer needs any special treatment either, at least not at the validation level. Because we'll hardcode that block being the sole one in the
content
region. - that leaves only "messages"! I personally think it merits getting almost the same treatment as the page title one, with one difference: if
\Drupal\experience_builder\Plugin\DisplayVariant\PageTemplateDisplayVariant
didn't encounter >=1 such block during rendering, then XB's page variant should just place it at the top of thecontent
region automatically, which is exactly whatBlockPageVariant
does:
// If no block displays status messages, still render them. if (!$messages_block_displayed) { $build['content']['messages'] = [ '#weight' => -1000, '#type' => 'status_messages', '#include_fallback' => TRUE, ]; }
If @lauriii agrees with that, then we'll have eliminated all of the validation challenges in this MR! It'll allow this MR to delete
\Drupal\experience_builder\Plugin\Validation\Constraint\ComponentTreeMeetsRequirementsConstraint::$nested
and related code. - 🇫🇮Finland lauriii Finland
Agreed that it would be great to place take care of placing the message. I like the proposal to place the message as a fallback on top of the content region. 👍
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
FYI: this blocks #3502769, see #3502769-4: [PP-2] auto-saved PageRegions may be invalid, but MUST NOT cause XB's previews to fail. → .
- 🇬🇧United Kingdom longwave UK
Moved this along a bit further, fixed all phpcs/phpstan issues and fixed some of the tests. More tests to fix and Wim's review points to address still.
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
Both @longwave and @f.mazeikis are out today, I'll finish this.
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
This is now down to a single last failure that's tricky to debug.
Critical bugs found:
- https://git.drupalcode.org/project/experience_builder/-/merge_requests/6...
- https://git.drupalcode.org/project/experience_builder/-/merge_requests/6...
- #17 was not yet addressed: https://git.drupalcode.org/project/experience_builder/-/merge_requests/6...
- lost test coverage: https://git.drupalcode.org/project/experience_builder/-/merge_requests/6... — fixing this also fixed #3502372 as predicted in #3502372-2: Hide main page content block from XB →
Interesting non-critical bugs found:
Now the word "template" in the XB codebase never refers to
PageTemplate
anymore.Out-of-scope
- #3507334, for which I rolled a patch over here already: #3507334-2: Deleting or updating a content entity should clear its values from the auto-save store →
- The pre-existing
🐛
Once previewed in XB an entity with no changes will still show up in "Review x changes"
Active
is also happening here now, but fixing that is out of scope here:
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
I've got it! 🥳 First green
block-form.cy.js
CI run.Wow, what a nightmare this was to debug — treating client-side data as unvalidated blobs that must be respected sure results in mind-bending debugging, because the bug/mistake can happen much earlier than the failing test! 😳🧟♀️
-
wim leers →
committed 696fdc82 on 0.x authored by
f.mazeikis →
Issue #3501600 by wim leers, f.mazeikis, longwave, effulgentsia, lauriii...
-
wim leers →
committed 696fdc82 on 0.x authored by
f.mazeikis →
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
Whew, it's finally in!
Didn't want to drag this >1000 LoC heisenbug-esque monster forward any longer. And didn't want to subject anybody to the painful review, although both @longwave and @larowlan already did. And, of course, I reviewed @f.mazeikis' original MR.
99% of the pain was in the auto-saving parts (see #25 for why — and OpenAPI doesn't help here at all because the client is supposed to be able to send arbitrary blobs!). The test failures when I started working on this were misleading/largely irrelevant, because the foundations were not yet working (see #23, "critical bugs").
The goal is always to first make the config entity iron-clad and thoroughly validated. Then build upon it. (And in this particular case, debugging was surprisingly painful.)
Quoting from #17:
If @lauriii agrees with that, then we'll have eliminated all of the validation challenges in this MR! It'll allow this MR to delete
\Drupal\experience_builder\Plugin\Validation\Constraint\ComponentTreeMeetsRequirementsConstraint::$nested
and related code.Extracted that into a simple follow-up: 📌 Remove ComponentTreeMeetsRequirementsConstraint::$nested Active .
More follow-ups tomorrow.
- 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10
After updating to 0.x and reinstalling seeing 🐛 Warning from block components when enabling for global template Active
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
All out-of-scope follow-ups, as promised in #27, for things I ran into while working on this MR:
- 📌 Remove ComponentTreeMeetsRequirementsConstraint::$nested Active
- 📌 Add ::getTree() and ::getInputs() helpers to ComponentTreeItem Active
- 📌 Clarify default 'resolved' vs 'source' value logic in GeneratedFieldExplicitInputUxComponentSourceBase::getClientSideInfo() Active
- 📌 Simplify ClientServerConversionTrait::clientLayoutToServerTree() Active