- Issue created by @longwave
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
Not all components have UUIDs
Which
\Drupal\experience_builder\Entity\Component
s do not have UUIDs? π€I think this MR is more broad than it needs to be.
- Components must be instantiated, so they can only be identified using something unique: a UUID.
- Slots (all kinds: SDCs' slots and theme regions, which conceptually are also slots) do not have UUIDs. Each slot has a name.
Components and Slots are two different concepts, why is it not okay for them to heave different identifiers?
(And yes, a slot instance is then identified by its containing component instance's UUID + the slot name. The only exception would be the "top-level slots", i.e. those at the
PageTemplate
level.) - π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
DM'd with @longwave.
IOW, the client side's
layout
tree contains 3 types of nodes:component
nodes are identified byuuid
, because they correspond to Components (\Drupal\experience_builder\Entity\ComponentInterface
instances) which have UUIDsslot
nodes are identified by a[component UUID, slot name]
pair, conveyed as a singleid
value that contains bothregion
nodes (needed for π Add support for global regions Active which this blocks) are identified only by aname
- π¬π§United Kingdom longwave UK
After discussing with Wim I think the above is correct. Unless there is a good reason not to, the front end will have to start considering slot and component nodes separately, which is safer and more correct - we should never be able to end up with a component containing another component or a slot containing another slot. A slot always has a name and belongs to a parent component, which is enough to uniquely identify it. So (ignoring regions for now) I think this can be represented in TypeScript as
export interface ComponentNode { nodeType: 'component'; uuid: UUID; type: string; slots: SlotNode[]; } export interface SlotNode { nodeType: 'slot'; name: string; components: ComponentNode[]; }
This does complicate functions such as
findNodeByUuid()
which now has two issues: it can no longer find slots, nor can it recurse easily as it needs to know about child structures. But this is solvable: we likely need to refactor it intofindComponent(uuid)
andfindSlot(uuid, name)
- andfindSlot()
can callfindComponent()
first and then retrieve the specific slot.@jessebaker I realise this likely causes significant rework on some of the frontend code and data structures, but what do you think of this proposal overall?
- π¬π§United Kingdom longwave UK
In fact regions are just a special case of slot, they only appear at the top level, maybe we only need this:
export interface RegionNode { nodeType: 'region'; name: string; components: ComponentNode[]; }
Regions can contain components, components can contain slots, slots can contain components, but no other combinations are allowed.
- π¬π§United Kingdom jessebaker
I agree with everything in #5, #6 and #7.
This will require a lot of refactoring on the front end but as @longwave says this is solvable and I do think is the correct path forward.
In fact I think there are already assumptions on the front end that components can only contain slots and slots can only contain components already, it's just not explicitly stated/defined in TS or anything. E.g. In
ComponentOverlay.tsx
I loop overcomponent.children
and for each one I render a<SlotOverlay />
. In turn the children inSlotOverlay.tsx
are all rendered as<ComponentOverlay />
s. - π¬π§United Kingdom jessebaker
I agree with everything in #5, #6 and #7.
This will require a lot of refactoring on the front end but as @longwave says this is solvable and I do think is the correct path forward.
In fact I think there are already assumptions on the front end that components can only contain slots and slots can only contain components already, it's just not explicitly stated/defined in TS or anything. E.g. In
ComponentOverlay.tsx
I loop overcomponent.children
and for each one I render a<SlotOverlay />
. In turn the children inSlotOverlay.tsx
are all rendered as<ComponentOverlay />
s. - π¬π§United Kingdom longwave UK
longwave β changed the visibility of the branch 3491013-not-all-components to hidden.
- Merge request !438Rework ApiLayoutController to send regions, components and slots with updated structure. β (Merged) created by longwave
- π¬π§United Kingdom longwave UK
I think the title summarises it better. The draft MR!438 makes the minimal server side changes required and will probably fail a lot of tests. I will fix up the server side where it breaks and hand over to @jessebaker to rework the client side.
- π¬π§United Kingdom jessebaker
In going through and trying to implement this I have consistently hit a pain point in working with the data formatted as described in #6 and #7
Without going into huge details about the painpoint I'm hitting, I think @wim leers suggestion in #5 to give each slot an id (changed from uuid) of
'id' => $component_instance_uuid . '/' . $slot_name,
will go a long way to fixing it. In simple terms, it will allow me to specify a specific slot without having to always keep track of the slots parent when recursively traversing the tree.So I think that would be:
export interface RegionNode { nodeType: 'region'; name: string; components: ComponentNode[]; } export interface ComponentNode { nodeType: 'component'; uuid: string; // unique uuid type: string; // corresponds to the drupal component id e.g 'sdc.experience_builder.druplicon' slots: SlotNode[]; } export interface SlotNode { nodeType: 'slot'; id: string; // made up of the parent components uuid and the slot's name. name: string; components: ComponentNode[]; }
From there, potentially one other QoL change for the front end would be to normalise 'uuid' on components and 'id' on slots to both be 'id' in the JSON but that is not critical and perhaps the clarity of giving them the correct names is more important.
- First commit to issue fork.
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
@longwave in #6: β you mean what I wrote in #5 I think?
@longwave #7++ ("regions are a special case of slots")
@jessebaker in #8: YAY! Music to my ears! π And the presence of those assumptions in the front end is indeed unavoidable, necessary and sane, which is exactly why I felt #5 would be a sensible step. Very glad to see you agreeing so strongly :)
@jessebaker in #13:
-
In simple terms, it will allow me to specify a specific slot without having to always keep track of the slots parent when recursively traversing the tree.
Why can't
findSlot(uuid, name)
usefindComponent(uuid)
, like so:export function findSlot(uuid: string, name: string): Node | null { const component = findComponent(uuid); // missing error handling for invalid name return component.name; }
?
-
perhaps the clarity of giving them the correct names is more important.
That's my current thinking, and my hope ππ€
-
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
YAY, all tests are passing, and it's now down to 15 TypeScript type checking errors! π
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
I see @longwave just implemented what @jessebaker proposed in #13. If it helps us land this faster, then I'm in favor! π
But I'd like to understand why it's necessary. I bet it's something to do with state tracking? A comment would go a long way ππ
- πΊπΈUnited States bnjmnm Ann Arbor, MI
I added a
3491013-but-with-ts-muted
branch which (as of rn at least) is the same a the primary MR, but with a bunch of ts-ignores so e2e tests can run and help us identify other places the FE code needs to change. I had hoped to find a few places to fix in the process but aside from fixing a few ts bits (and avoiding a few additional ts-ignores), none of the fixes were particularly obvious (@jessebaker has said as much). Hope the e2e-running branch at least helps things a bit.
- π¬π§United Kingdom longwave UK
Merged 0.x, copied and updated the relevant data-model.md changes from π Add support for global regions Active
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
I reviewed in-depth and RTBCβd β now this just needs @travis.cardenβs approval for the
/openapi.yml
changes β @travis.carden, IMHO this is a big step in the right direction, although itβs not yet perfect.But β¦ given that the changes here block several critical issues (see related issues), I decided to not wait for @travis.carden to approve. The changes here are around refactoring the client-side data model, which affects some request & response bodies, and this MR definitely updates
/openapi.yml
accordingly.There is this:
+ // TODO refactor of this file should remove this ts-ignore once Slots and Component rendering is correctly separated out.
β¦ and in that MR, we'll be perfectly positioned to split
/openapi.yml
'sLayoutSlot
intoLayoutRegion
andLayoutSlot
.@travis.carden, if/when you approve, please go ahead and merge this too, because per @alex.bronstein, this is blocking a lot of things: https://acquia.slack.com/archives/C06M3JQJG1M/p1733849815358459
-
wim leers β
committed ac5ae1d8 on 0.x authored by
longwave β
Issue #3491013 by jessebaker, longwave, bnjmnm, wim leers: Rework layout...
-
wim leers β
committed ac5ae1d8 on 0.x authored by
longwave β
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
All test failures are failures on
0.x
too, all happening due to upstream changes in Drupal core11.1.x
. So, went ahead and merged this, bypassing @travis.carden's approval for reasons cited in #21.Epic work, all of you, but especially @jessebaker! π