Create HTTP Endpoint for View modes/content templates

Created on 12 August 2025, about 2 months ago

Overview

The UI will need to show the view modes of all entity types are the opt-ed into XB templating

Proposed resolution

Provide an HTTP API endpoint that will return list of all XB template enabled bundles and their view mode
Until will make the UI to opt-in bundles lets have this hardcode to assume all node types are enabled.
For each mode we should have metadata
Proposed format

$view_modes = [
      'node' => [
        'page' => [
          'full' => [
            // Whether template has auto-save changes. This can be tru even if
            // existing_template is false since we auto-save templates before
            // first publishing without creating a new saved template.
            'auto-save-changes' => TRUE,
            // Where the there is an existing template saved.
            'existing_template' => TRUE,
            // The ID does require an exisitng template because it is based on
            // entity props that can't be changed.
            'template_id' => 'node.page.full',
            // do we need this or can the client just make it?
            'layout_url' => '/xb/api/v0/layout-template/node/page/full/{entity_id',
          ]
        ]
      ]
    ];

We could also flatten it more

$view_modes = [
          'node.page.full' => [
            'entity_type' => 'node',
            'bundle' => 'page',
            'view_mode' => 'full',
            // Whether template has auto-save changes. This can be tru even if
            // existing_template is false since we auto-save templates before
            // first publishing without creating a new saved template.
            'auto-save-changes' => TRUE,
            // Where the there is an existing template saved.
            'existing_template' => TRUE,
            // The ID does require an exisitng template because it is based on
            // entity props that can't be changed.
            'template_id' => 'node.page.full',
            // do we need this or can the client just make it?
            'layout_url' => '/xb/api/v0/layout-template/node/page/full/{entity_id',
      ]
    ];

Probably just depends on what is prefered by the UI

User interface changes

πŸ“Œ Task
Status

Active

Version

1.0

Component

Internal HTTP API

Created by

πŸ‡ΊπŸ‡ΈUnited States tedbow Ithaca, NY, USA

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @tedbow
  • πŸ‡ΊπŸ‡ΈUnited States tedbow Ithaca, NY, USA
  • πŸ‡ΊπŸ‡ΈUnited States hooroomoo

    My preference would be the first way (not flat). And yes the frontend can construct the 'layout_url' => '/xb/api/v0/layout-template/node/page/full/ given the response.

    $view_modes = [
          'node' => [
            'page' => [
              'full' => [
                // Whether template has auto-save changes. This can be tru even if
                // existing_template is false since we auto-save templates before
                // first publishing without creating a new saved template.
                'auto-save-changes' => TRUE,
                // Where the there is an existing template saved.
                'existing_template' => TRUE,
                // The ID does require an exisitng template because it is based on
                // entity props that can't be changed.
                'template_id' => 'node.page.full',
              ]
              'teaser' => [
                'auto-save-changes' => FALSE,
                'existing_template' => FALSE,
                'template_id' => 'node.teaser.full',
              ]
            ]
            'article' => [
              'full' => [
                'auto-save-changes' => FALSE,
                'existing_template' => TRUE,
                'template_id' => 'node.article.page',
              ]
              'teaser' => [
                'auto-save-changes' => TRUE,
                'existing_template' => TRUE,
                'template_id' => 'node.article.teaser',
              ]
            ]
          ],
        ];
  • πŸ‡¬πŸ‡§United Kingdom f.mazeikis Brighton
  • πŸ‡³πŸ‡±Netherlands balintbrews Amsterdam, NL

    The issue summary already talks about nodes only, but I just wanted to reinforce that at this stage we're only targeting node bundles, no other entity types are in scope.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    The issue summary already talks about nodes only, but I just wanted to reinforce that at this stage we're only targeting node bundles, no other entity types are in scope.

    FYI this is enforced since https://git.drupalcode.org/project/experience_builder/-/commit/843e7b0b1...

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Please follow the patterns set in πŸ“Œ Move `PropSourceEndpointTest` into new `XbConfigEntityHttpApiTest::testComponent()` Active :

    • add new method to ApiUiContentTemplateControllers
    • add success test coverage + comprehensive client error test coverage ApiUiContentTemplateControllersTest
    • expand OpenAPI spec
  • πŸ‡ΊπŸ‡ΈUnited States hooroomoo

    Mentioned this on a call but just want to record here, can the view mode response can also provide a key with the first available node entity that the frontend can use to display the template with? And if a content of that bundle doesn't exist yet then it can be null or something and the frontend can handle accordingly to maybe show an warning message in the UI to require a user to create content for it if they want to view the template for that bundle in XB.

  • πŸ‡¬πŸ‡§United Kingdom f.mazeikis Brighton

    I've had a chat with @hooroomoo about this and we most likely will need two or three separate endpoints:

    1. Endpoint that provides a list of Template entities, grouped by entity type and bundle
    2. Endpoint that provides a complete list of existing Drupal view modes
    3. Endpoint that provides a list of Drupal view modes for specific combination of entity type and bundle

    Current MR only adds #1 and is not complete, but it might be decent place to start for FE work until we complete rename process.

  • Pipeline finished with Failed
    about 1 month ago
    Total: 755s
    #583417
  • Pipeline finished with Failed
    about 1 month ago
    #583896
  • Pipeline finished with Canceled
    about 1 month ago
    #583911
  • Pipeline finished with Failed
    about 1 month ago
    #583915
  • Pipeline finished with Success
    about 1 month ago
    #584000
  • Pipeline finished with Failed
    about 1 month ago
    Total: 969s
    #587238
  • πŸ‡¬πŸ‡§United Kingdom f.mazeikis Brighton
  • Merge request !10Resolve #3541015 "Create http endpoint" β†’ (Merged) created by tedbow
  • πŸ‡ΊπŸ‡ΈUnited States tedbow Ithaca, NY, USA

    currently creating another MR for canvas

  • πŸ‡ΊπŸ‡ΈUnited States tedbow Ithaca, NY, USA

    Got new MR https://git.drupalcode.org/project/canvas/-/merge_requests/10 almost passing

    assigning it back to @wimleers because @f.mazeikis had assigned to him

  • πŸ‡¬πŸ‡§United Kingdom f.mazeikis Brighton

    Few more things to do after yesterdays conversations, assigning to myself

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Well, I started a review already anyway, and I think I found one seemingly quite big problem πŸ˜…

    Plus, I don't see why this is unable to use the existing infrastructure we've carefully grown to avoid duplication and improve maintainability: why can't this use CanvasHttpApiEligibleConfigEntityInterface?

    Details on the MR.

  • πŸ‡¬πŸ‡§United Kingdom f.mazeikis Brighton

    f.mazeikis β†’ changed the visibility of the branch 3541015-create-http-endpoint to hidden.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί
                // first publishing without creating a new saved template.
                'auto-save-changes' => TRUE,
    

    is not in this MR. Is it obsolete?

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Been pairing with @f.mazeikis to get this across the line!

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    🚒, which means ✨ Create new Templates menu Active is now unblocked!

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

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

    Maintainers, please credit people who helped resolve this issue.

  • πŸ‡ΊπŸ‡ΈUnited States tedbow Ithaca, NY, USA

    There is bug where suggestedPreviewEntityId is being sent back as a string not int.

    Will post fix and test in new MR

  • Merge request !33Resolve #3541015 "Type fix" β†’ (Merged) created by tedbow
  • πŸ‡ΊπŸ‡ΈUnited States tedbow Ithaca, NY, USA
  • πŸ‡ΊπŸ‡ΈUnited States hooroomoo

    Something came up while i started working on ✨ Create new Templates menu Active :

    So the frontend has to display the content types and also the templates in the left menu. The below is currently rendering what is returned from /canvas/api/v0/config/content_template. But the issue is, that endpoint only provides bundles that have existing content templates. But I believe we want to render all the available content types even if it doesn't have a template yet (just have an empty accordion).

    /canvas/api/v0/ui/content_template/view_modes/node returns all the available bundles so we can maybe use that endpoint to display the left menu, but endpoint doesn't provide a bundle label.

    I see 2 ways to solve this:

    #1. If the frontend is going to use /canvas/api/v0/ui/content_template/view_modes/node to display the menu on the left, then we need the bundle label available. But the downside of this is we would need to make an extra request to the content template to get the content template specific info like suggestedPreviewEntityId and id which is cumbersome and doesn't really make sense to use the view mode endpoint to display the template menu.

    #2. If the frontend uses canvas/api/v0/config/content_template/ to display the left menu, then that endpoint needs to also provide the available bundles that don't have any existing templates yet.

    I prefer #2, to avoid the downside I mentioned. I don't know if there are any backend ramifications though.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    #23: πŸ₯² That was one of the last tweaks/fixes we did, and tests were green. Thanks, LGTM!

    #26:

    Ah but this is slightly different! It’s not asking to list view modes that don’t have a template yet. It’s just asking to create the full hierarchy of (supported) content entity types and bundles!

    That seems totally doable! πŸ‘

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    @tedbow in#23 and in your !33 MR: you're making it crystal clear that I did not review CanvasConfigEntityHttpApiTest::testContentTemplate()() at all 😰 I deemed it low-risk enough to unblock @hooroomoo.

    The good thing @hooroomoo was unblocked. πŸ‘

    The bad news is that you found this small bug, but then also found missing test coverage, with inaccurate comments, and in looking at it now, there's even more missing test coverage and even an unaddressed @todo πŸ˜… Fixing that.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    there's even more missing test coverage and even an unaddressed @todo

    And turns out that the test coverage that did land is not trustworthy enough 😰, because it's apparently consistently relying on ContentTemplate::normalizeForClientSide() to generate test expectations. Which means the expectations and the actual values are generated by the same code, which undermines the value of the tests.

    I'll tackle that while addressing #26 in a separate MR. @tedbow's MR is good to go as-is: it fixes the bug, has test coverage, and fixes any comments that are copy/paste remnants from other CanvasConfigEntityHttpApiTest::test*() methods πŸ‘

  • Merge request !1507Draft: Resolve #3541015 "All bundles" β†’ (Closed) created by wim leers
  • Merge request !34Resolve #3541015 "All bundles" β†’ (Merged) created by wim leers
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Per #26:

  • Merge request !35Resolve #3541015 "Missing tests" β†’ (Merged) created by wim leers
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Both MRs (expand/fix tests + build what @hooroomoo requested in #26) are on the verge of landing πŸ‘

    Result for #26, if I temporarily peek into the future and allow multiple content entity types, and not just node:

    {
      "node": {
        "label": "Content types",
        "bundles": {
          "article": {
            "label": "Article",
            "viewModes": {
              "full": {
                "entityType": "node",
                "bundle": "article",
                "viewMode": "full",
                "viewModeLabel": "Full content",
                "label": "Article content items β€” Full content view",
                "status": false,
                "id": "node.article.full",
                "suggestedPreviewEntityId": 1
              }
            }
          },
          "page": {
            "label": "Basic page",
            "viewModes": []
          }
        }
      },
      "user": {
        "label": "Users",
        "bundles": {
          "user": {
            "label": null,
            "viewModes": []
          }
        }
      },
      "taxonomy_term": {
        "label": "Taxonomy",
        "bundles": {
          "tags": {
            "label": "Tags",
            "viewModes": []
          }
        }
      }
    }
    
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    And it's done πŸŽ‰ Whew!

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

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

    Maintainers, please credit people who helped resolve this issue.

Production build 0.71.5 2024