XB week 12: component previews & StorablePropShape

published on August 27, 2024

The back-end heart of Experience Builder (XB) is its two-property field type. Thanks to Ted “tedbow” Bowman, the tree field property is now strictly validated, which is essential to ensure both data integrity and the ability to evolve the codebase rapidly and confidently. Crucially, this validation constraint is used to validate both content and configuration, just like the validation that was added in week 10.

That validation finally unblocked #3446722: Introduce an example set of representative SDC components; transition from “component list” to “component tree”: now that Ted landed the necessary validation, it makes sense to add Kyle “ctrladel” Einecker’s set of Single Directory Components (SDCs) that Lauri has confirmed to well represent the spectrum of SDC functionality XB must support.
Ted will change the default component tree that XB configures for articles, so that we’ll start seeing Kyle’s two_column SDC by default!

To assist Ted, I updated the XB field type’s computed hydrated property to support hydrating component trees instead of just component lists, and updated the “preview” route to use that logic 1.
Ted already landed validation, I took care of rendering, so now Ted can focus on the remaining bits … because until now, we’d been testing/developing XB with only a handful of sample components — we fully expect this to reveal a bunch of missing things. That’s exactly why getting a representative set of SDCs into the XB codebase is important, even if eventually they may only be used in tests.

Hopefully that will land next week!

Hearing the term “routing” in a Drupal context typically means “server-side routing”. But for an extensive JS application, client-side routing is important too: it allows sharing a URL with a friend/colleague to invite them to collaborate on a particular bit in the content being created. That’s why Jesse “jessebaker” Baker and Ben “bnjmnm” Mullins landed client-side routing for XB, after having asked for feedback from the community on which direction to take (thanks Bálint “balintbrews” Kléri, Ronald “roaguicr” Aguilar, Kyle and Lee “larowlan” Rowlands for your input!), landed on React Router. The implementation will likely evolve, but a basic implementation is now in place, and includes test coverage.

Related to routing, but on the back-end side: Lee updated XB’s server-side routes to expect an entity type + ID, rather than hardcoding them all to node one. This is a welcome improvement, but would not have happened if not for Lee or somebody else in the community: for the team working full-time on XB this isn’t a priority yet, because we’re prioritizing the hard stuff — the known unknowns. Still, we definitely welcome MRs like these, and will happily review & merge them!

I know y’all are waiting for interesting progress on the experience of using XB — this week’s key progress on that front is brought to you by Ben!
Choosing a component to pick just based on the name might be okay … but an instantaneous visual preview would be better, right? That’s exactly what he landed in #3462636:

Previewing a component upon hovering it in the component list. Components temporarily have a loud background color.
Previewing a component upon hovering it in the component list. Components temporarily have a loud background color. Issue #3462636, image by Ben.

The funniest bugfix of the week is brought to you by Utkarsh “utkarsh_33”: the SDC prop labels were present on field widgets, but were invisible :D

Finally, in the “improve DX & velocity” department, the eslint prettier configuration was updated, which gets us closer to Drupal core’s configuration for JS. Thanks to Ivan “finnsky” Berdinsky, Ben, Gaurav “gauravvvv”, Daniel “DanielVeza”, Lee and Harumi “hooroomoo” Jang — Harumi captured the impact well:

Looks good! Will save headaches

:)

Computing a StorablePropShape

Back to the back-end side, to end this week’s update in a very deep place (but also a very interesting place!): XB gained the ability to compute a field type + storage settings + instance settings for a given SDC prop shape (the normalized subset of an SDC prop’s JSON schema that affects the shape of data it expects — the title, description, examples etc. in the JSON schema are irrelevant from this point of view; I named this a PropShape).
Until now, XB has only been using matching. But that can only get us so far — for example, SDCs often have props whose JSON schema looks like this:

    style:
      type: string
      enum:
        - primary
        - secondary

To populate this SDC prop, XB must store a string (logical choice: Drupal core’s string field type), but not just any string: only primary or secondary. Drupal core has an answer for this too: the list_string field type. But the matching that was hitherto used requires either a field type that allows precisely those 2 values, or an existing list_string field instance that is configured to allow those 2 values. Clearly, that’s likely to result in zero matches, because the chances are vanishingly small that a Drupal site has a pre-existing field instance configured exactly like that. And that is just one example: many SDCs will have different allowed values.

That’s where computing rather than matching becomes relevant: use logic to compute what exact shape (in this case: a type: string that also specifies an enum: […]) requires which field type (list_string) and which corresponding field storage+instance settings (here only storage settings: allowed_values: [ {value: primary, label: primary}, {value: secondary, label: secondary} ]). The computed result is represented by a StorablePropShape.

And that is necessary for XB users to fully benefit from the work Ted is doing on #3446722: many of those representative SDCs are indeed using enum: otherwise you’d not be able to edit component instances that will be placeable once Ted’s done!

This infrastructure also paves the path to something else: allowing those computed field type + widget decisions to be altered. For example, when the Media Library module is installed and a media type that uses the image MediaSource plugin is present, an SDC with a prop that expects an image should no longer use the image field type + widget, but the Media Library widget. So I worked with Ted and Ben to introduce hook_storable_prop_shape_alter(), and made XB implement it on behalf of the media_library module.

This doesn’t mean that matching goes away: that will remain relevant for identifying which existing structured data can be used to populate an SDC prop. Much more work is needed to make XB’s matching ability complete, but that work is for after the 0.1.0 goals for DrupalCon Barcelona.

Week 12 was July 29–August 4, 2024.


  1. Instead of having its own logic that was somewhat different: DRY↩︎