Problem/Motivation

A page is assembled from several displays at once: a page layout, an entity view display, an entity override, a Views display. Each is stored elsewhere and edited in its own builder, so moving between the levels means leaving the tool. The level you need is often one that is not built with Display Builder yet, which is exactly where users get stuck.

Proposed resolution

Add an Instances sidebar panel that lists every display a user may travel to, grouped by buildable provider, with the current one marked.

  • It lists displays, not instances, and is strictly read-only: it never creates or saves an Instance entity as a side effect of rendering.
  • Displays not built with Display Builder are listed too, hidden behind a toggle, and linked to their own settings page to enable one there.
  • Each row carries a link to where that display is configured (Manage display, the Views edit form, the page layout form). An override points at the display it overrides.
  • A filter, and a per-group cap with a View more button, keep the panel usable on sites with many displays.
  • A listing that is bounded says so: entity overrides show the most recent 25 per display.
  • New documentation page, docs/how-displays-nest.md, and a workflow sentence in the keyboard help.

Here is a capture of new instances list.
demo

API changes

  • New Drupal\display_builder\DisplayReference value object.
  • DisplayBuildableInterface::collectDisplays() and ::collectDisplaysBound() added. DisplayBuildablePluginBase returns an empty array and NULL, so existing plugins need no change.
  • collectDisplays(), collectDisplaysBound() and collectInstances() are instance methods, not static. A listing is answered by a plugin built with no configuration, which restores dependency injection: the \Drupal::service() calls inside them are gone, and InstanceListBuilder no longer passes an entity type manager into a static that declared no parameters and ignored it.
  • getPrefix() removed from the interface. It stays on the base class, where every caller is a plugin asking about itself.
  • EntityView::manageDisplayUrl() is public, so an override can reuse it.
  • Two lazy-resolution fixes of the same shape, both of which made a label silently NULL: ViewDisplay::getDisplayLabel() read $this->extender instead of calling ::getExtender(), so Views displays were never listed at all; EntityViewOverride::getDisplayLabel() read $this->field instead of calling ::getField(), so it only worked when a previous call had happened to resolve it.

User interface changes

New Instances panel, enabled by default and added to existing profiles by display_builder_post_update_3().

Remaining tasks

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mogtofu33 created an issue. See original summary.

mogtofu33’s picture

Assigned: mogtofu33 » Unassigned
Status: Needs work » Closed (duplicate)
Issue tags: -display_builder-1.0.0-beta7

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

mogtofu33’s picture

Assigned: Unassigned » mogtofu33
Status: Closed (duplicate) » Active

mogtofu33’s picture

mogtofu33’s picture

Issue summary: View changes
mogtofu33’s picture

Issue summary: View changes
mogtofu33’s picture

Assigned: mogtofu33 » pdureau
Status: Active » Needs review
ipumpkin’s picture

The `entity override instance` should only display the list of instances corresponding to different languages ​​for the current entity when the current entity is being overridden. This list is essentially a translation list. Otherwise, it should not be displayed by default, and the number of instances could be very large.

translation override issue here need review:
https://www.drupal.org/project/display_builder/issues/3611826

mogtofu33’s picture

We will be able to handle translation in it's own Epic to have a full picture and not partial fixes, created as #3615902: Translation support.
Starting point will probably be when #3555110: Symmetric translation is ok, then #3611826: Display Builder override saves to wrong language on multilingual sites.

For now it's not in the scope of this issue but that's good to foresee what could help or block future work. Created specific issue under translation plan.

the number of instances could be very large

That's why there is a limit of 25

ipumpkin’s picture

@Jean Excellent planning. I hope the translation issues can be resolved soon. I'm preparing to use DS in the production environment.

mogtofu33’s picture

Assigned: pdureau » mogtofu33
Status: Needs review » Needs work

mogtofu33 changed the visibility of the branch 3615031-ux-nesting to hidden.

mogtofu33’s picture

Title: UX for nesting displays in displays comprehension » Enhance instances list for better navigation
Assigned: mogtofu33 » pdureau
Issue summary: View changes
Status: Needs work » Needs review

Issue was too big and not clear, reworked as an instances list enhancement.

An other issue will propose something on the placeholders / non renderable.

mogtofu33’s picture

Issue summary: View changes
StatusFileSize
new299.31 KB
mogtofu33’s picture

mogtofu33’s picture

Issue summary: View changes
mogtofu33’s picture

Issue summary: View changes
pdureau’s picture

Assigned: pdureau » mogtofu33
Status: Needs review » Needs work

I take time reviewing this MR because, if merged in the current state, it will count for 5% of the PHP code (comment, blank lines & tests excluded) of the full project.

Code overview

Most of the added logic is in InstancePanel and in the implementations of those 3 new DisplayBuildableInterface methods:

  • ::getDisplayLabel(): ?string;
  • ::collectDisplays(array $options = []): array;
  • ::collectDisplaysBound(): ?TranslatableMarkup;

Code review

⚠️ InstanceInterface::getBuildable(): ?DisplayBuildableInterface; has been added with the corresponding implementation but it is called only in:

  • in Instance::label() so inside the same class
  • in the corresponding InstanceTest::testLabelWithoutBuildable()

⚠️ Why DisplayBuildablePluginBase::getViewModeLabel() and ::getBundleLabel()? This logic (and the corresponding entity_type.bundle.info) seems specific to display_builder_entity_view scope, do we?

⚠️ ::getPrefix() has been removed from the DisplayBuildableInterface but it is still a public method in DisplayBuildablePluginBase. Why? For information, in #3573905: Simplify DisplayBuildableInterface we successfully moved this method to protected.

⚠️ A new "floating" DisplayReference utility class (called by InstancePanel and implementations of DisplayBuildableInterface::collectDisplays()). There is nothing in the Drupal API which can "carry" this logic? If not, it is OK.

⚠️ ContextualFormPanel is the second most changed file of the MR but it is hard to see how it belongs to the current work. Some added logic is specific to MainPageContentSource from display_builder_page_layout according to the comment but to display_builder_entity_view according to the code.

⚠️ I have a warning in every display builder page, after switching to the branch, a updb and cache rebuild:

Undefined array key "instance_id" in Drupal\display_builder_test\Plugin\display_builder\Buildable\TestDisplayBuildablePlugin->__construct() (line 53 of TestDisplayBuildablePlugin.php).

Feature review

Still exploring, looks cool so far... but we can discuss the code review first.

By the way

In a #3542796: Preview of view sources comment, it was said:

A change of preview placeholder is proposed in #3615031: Enhance instances list for better navigation so probably better to have it merged before, then back to this one, then a follow up issue for views placeholder.

But i didn't see this while doing the review.

mogtofu33’s picture

Will do 1, 2, 3
5 as well, it's caused by history of this task before split. The comment is wrong I'll clean.

4: no core we can use for that I know of, for this mix label+url + state (as seen from constructor), could have a follow up for investigation but I like the return type, it's clean. core Link Or Url miss our specific extra cases. Formatting methods keywords and tooltip could move out as they are display, perhaps InstancesPanel.

mogtofu33’s picture

Assigned: mogtofu33 » pdureau
Status: Needs work » Needs review

InstanceInterface::getBuildable() removed and now a private Instance::getDisplayLabel()

getViewModeLabel() / getBundleLabel() moved to EntityDisplayLabelTrait in display_builder_entity_view, and entity_type.bundle.info is gone from DisplayBuildablePluginBase.
composeDisplayLabel() stayed on the base: the format is a contract on the interface and three submodules call it. While moving it I also switched the view-mode lookup to core's entity_display.repository, which is one cached array per entity type instead of a config-entity load per row, and it honors hook_entity_view_mode_info_alter().

getPrefix(): now protected static, using the approach from your MR 235. The entity_delete hook builds the plugin instead of composing the ID, which on this branch is shorter than ref MR because EntityViewOverride already accepts display and entity config keys. Two side effects worth flagging: a return in that loop should have been continue, so a bundle with two override displays previously stopped deleting after the first miss; and the deletes are now batched into one call. Tests use a literal PREFIX constant, as !235 does, which also means they assert the stored ID format instead of deriving it from the code under test.

One correction to my own docblock while I was there: the prefix was never actually encapsulated. InstanceAccessControlHandler, PageVariantSubscriber and BackButton all read $definition['instance_prefix'] directly, each hand-rolling the same scan. Noted in the docblock as a follow-up.

DisplayReference kept, and I would argue it is a value object rather than a floating utility. Stronger reason is the contract: collectDisplays(): DisplayReference[] is implemented independently by four plugins in three submodules, and the alternative is untyped arrays with magic keys that PHPStan cannot check. Moved display methods keywords() and tooltip() into InstancesPanel.

ContextualFormPanel: the @see MainPageContentSource was simply wrong and is gone; the prose now says plainly that the page layout boundary is not handled here. The duplicated manageDisplayUrl() is gone too: it asks the buildable through getDisplayUrlFromInstanceId() and only adds the field_ui route guard.

I will create a follow up for some loose end and non blocking.

pdureau’s picture

DisplayReference kept, and I would argue it is a value object rather than a floating utility.

OK, good, no issue with that. I was just asking if there was already something defined in the Drupal world we can leverage.

I will resume my review soon, with a focus on the functional part.

pdureau’s picture

I still have this warning on display builder pages:

Undefined array key "instance_id" in Drupal\display_builder_test\Plugin\display_builder\Buildable\TestDisplayBuildablePlugin->__construct() (line 53 of TestDisplayBuildablePlugin.php).

Review in progress.

Instance sidebar

The feature is cool but it looks like a power users one which have a risk to confuse the casual users. We need to be especially careful because of those 2 reasons:

  • it is the only island not telling about or active on the display we are currently building, but about a global state of the website
  • the island is activated by default, so will be seen by most of the users

I am genuinely asking myself (no answer yet, not pushing anything for now):

  • Do most of the users need all this information? Seeing all buildable types (Page Layout, ) instead of only the one we are working one? Seeing the "not built yet"? Direct access to the settings (which are rarely used once Display Builder is activated for a display)?
  • Do we accept the added code load (still an additional 5% of PHP) for this feature? Is focusing the UX also a way of simplifying the code?

⚠️ The display we are currently building is also shown in the list. When i start a new display, i see it as "empty", it stays empty when i publish it. I need to refresh the page to see the "empty" removed.

⚠️ "Not built yet" means "not manage by display builder" and show displays which can be built from other tools.

⚠️ The settings link of "Entity View Override" is loading entity view display page. Is it the one people doing content override need? Would the entity edit form be better?

ContextualFormPanel

I am still struggling to understand the change: "Build the line naming the display this node renders, when there is one." for 3 reasons:

  • It doesn't seem related to the rest of the MR and may deserve its own discussion and work
  • It is still very bound to entity_view with a logic around entity types, bundles, view modes, targets...
  • What do i need to do to test it in the UI? I am building an article display, using an entity reference field to tags vocabulary and a rendered entity formatter to a display also build with Display Builder, I see nothing special in the panel.
mogtofu33’s picture

Thanks for the review. Fixed requests, and cut the ContextualFormPanel change.
EntityViewOverride link was for an other issue but temporarily fixed here to avoid a nonsensical link. Point to the edit content, we can see what's best next.

Do most of the users need all this information? [...]

Not all but the 'builder' of the site yes. And the list is based on access, so builder without specific access (Page layout, Views, Field UI...) do not see them. For me it match our priority persona builder. Even a possible 'Editor'.

Do we accept the added code load (still an additional 5% of PHP) for this feature? Is focusing the UX also a way of simplifying the code?

Yes, my priority is UX for adoption and there is no correlation between code size and focus/clean UX, there is an elegance doing both, but not a priority for me.

⚠️ "Not built yet" means "not manage by display builder" and show displays which can be built from other tools.

I would prefer a clear proposition of wording, the shortness was on purpose for visual, extended to Not using Display Builder as I want to try to keep one line.

A follow up can include better wording, help text...

The fact that it can overlap with other tools is not an issue for me atm, we can plan better if required as follow up.

pdureau’s picture

Status: Needs review » Needs work
StatusFileSize
new34.71 KB

cut the ContextualFormPanel change.

Great, but we have still the corresponding line in .phpmd.baseline.xml:
<violation rule="PHPMD\Rule\Design\WeightedMethodCount" file="/builds/project/display_builder/src/Plugin/display_builder/Island/ContextualFormPanel.php"/>

Instances UI

A lot of markup and CSS has been generated for this feature, especially in /assets/css/instances.css. Because of its specific design implementation, the panel looks weird, a bit out of place in the Display Builder UI, with the bullet list, specific sizing and spacing, underline blue links..:
tests

We are using a design system, Shoelace, to keep UI consistency and to delegate design choices and implementation to upstream. So, why not using Shoelace components here? For example:

  • sl-menu-label instead of .db-instances__title
  • sl-menu-item instead of .db-instances__item, the settings link can be put in suffix slot
  • sl-menu-item[disabled] instead of .db-instances__item--not-built
  • sl-divider in between groups
  • ...

Also:

  • Every "not built" list item as the popover title: "Not using Display Builder. Enable it on Manage display.", whcih make sense only for EntityView buildables.
  • "Filter" label in displays filter bar would be more explicit as "Filter display"

About Views

There are 2 issues:

  • "not built" list items are displayed as an empty list item instead of hidden (see screenshot)
  • displays not buildable with Display Builder are present in the list. With a fresh Drupal 11.4 install, more than half of the listed displays don't belong here.

Because I have already play with a solution while investigating, I will propose a little commit (in a different MR of course), so i keep the ticket on my side for a few minutes more.

By the way

As previously stated, it was said on a #3542796: Preview of view sources comment:

A change of preview placeholder is proposed in #3615031: Enhance instances list for better navigation so probably better to have it merged before, then back to this one, then a follow up issue for views placeholder.

Is it work expected in another ticket?

pdureau’s picture

Assigned: pdureau » mogtofu33

Commit pushed (in a distinct MR to not mess with your work): https://git.drupalcode.org/project/display_builder/-/merge_requests/346/...

Addressed:

  • ✅ "Filter" label in displays filter bar would be more explicit as "Filter display"
  • ✅ Views display: "not built" list items are displayed as an empty list item instead of hidden (see screenshot)
  • ✅ Views display: not buildable with Display Builder are present in the list. With a fresh Drupal 11.4 install, more than half of the listed displays don't belong here.

I can also try to propose the conversion of instances.css to Shoelace if you want.

mogtofu33’s picture

Assigned: mogtofu33 » pdureau
Status: Needs work » Needs review

Very strange I never had this bullet list or empty lines, which theme are you on? On Bootstrap, Test or even Olivero I do not have that?

Edit: Ok I see with Claro an issue.

So let move to button component, I do not think menu is valid here as I want to match neighbor 'Libraries'.

For placeholder as I noted on comment #16 that this job has been removed from this issue as it was making it too big. We'll require an other issue which I have locally but not created yet.

mogtofu33’s picture

Assigned: pdureau » mogtofu33
Status: Needs review » Needs work
mogtofu33’s picture

Assigned: mogtofu33 » pdureau
Status: Needs work » Needs review

Rebased + views change plus wording.

Moved to web components to avoid bleeding.

pdureau changed the visibility of the branch 3615031-instances-displays-list-pdu to hidden.

pdureau’s picture

Assigned: pdureau » mogtofu33
Status: Needs review » Reviewed & tested by the community

For placeholder as I noted on comment #16 that this job has been removed from this issue as it was making it too big. We'll require an other issue which I have locally but not created yet.

OK thanks, i missed this. Let's wait the next issue.

So let move to button component, I do not think menu is valid here as I want to match neighbor 'Libraries'.

Cool.

So, we reached RTBC, with only one last change before merging: are you OK to add 2 more conditions for the list of View displays?

--- a/modules/display_builder_views/src/Plugin/display_builder/Buildable/ViewDisplay.php
+++ b/modules/display_builder_views/src/Plugin/display_builder/Buildable/ViewDisplay.php
@@ -396,6 +396,14 @@ final class ViewDisplay extends DisplayBuildablePluginBase {
       return FALSE;
     }
 
+    if (\str_starts_with($display->getOption('path') ?? '', 'admin/')) {
+      return FALSE;
+    }
+
+    if ($display->getOption('use_admin_theme')) {
+      return FALSE;
+    }
+
     return TRUE;
   }

They are inspired from core/modules/views/src/Plugin/views/display/Page.php, lines 260-265, and they skip displays which are rendered with admin theme: /admin/content, /admin/people...

However, do we need to consider the View displays rendered with admin theme but where Display Builder has been used?

Edit: Oops, I am not sure we have addressed everything from #3614998: Island instances list navigation enhancement:

  • is "Instances" the correct wording here? It is the technical term and the one we use in Admin UI, for site admins, but it may confusing for casual users. Why not something like "Displays", "All displays" or "Displays overview"?
  • do we display the instances of the same "buildable" first instead? For example, if we build a page layout, we have the page layouts list first?
mogtofu33’s picture

Assigned: mogtofu33 » Unassigned
Status: Reviewed & tested by the community » Fixed

Views filter added plus tests. Follow up issue for wording.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • mogtofu33 committed fd05c573 on 1.0.x
    task: #3615031 Enhance instances list for better navigation
    
    By:...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.