Problem/Motivation

Drupal is gearing towards using Canvas (previously called experience builder) module in the future for creating and editing content. A Canvas page is a separate new entity type. Make this module compatible with Canvas pages.

CommentFileSizeAuthor
#3 sitemap-screenshot.png119.46 KBflyke

Comments

flyke created an issue. See original summary.

gbyte’s picture

Issue summary: View changes

Good point and certainly important!

Last time I checked (which was a couple of months ago), experience builder only worked on a modified testing version of Drupal CMS. Can one install it mainline Drupal 11 yet?

@flyke Would you be willing to create an MVP merge request for this?

flyke’s picture

StatusFileSize
new119.46 KB

At the moment, I'm recreating our company's Starterkit, which we use as a base for new projects, to use Canvas.
In the early days, our starterkit used Paragraphs and had lots of paragraph types buit in. Later on I rewrote it to use Layoutbuilder and it had lots of content block types built in. Now I'm rewriting it again and I'm creating SDC's (single directory components) instead of content block types. Currently I'm using Drupal 11.2.7 + Canvas 1.0.0-rc2.

Can you install it mainline Drupal 11 ?
If your site is not multilingual, I would say yes, you can actually use it.
Right now I'm postponing the multilanguage part a bit, thats the next thing I'll be testing and working on for Canvas after I've created all necessary SDC's that we need.
As a test, I'm recreating lots of advanced pages in our starterkit with Canvas from some of our clients projects to make sure canvas can do everything we want for adding content, and it actually works great.
There are a few things that bother me a bit
- Gone is the use of image styles/responsive image styles, so you use the original image src and create an srcset inside the image.twig file. I'm not so good at that so for now I'm just loading original images (bad because my images are not responsive at the moment) until I take the time to study and test how to do that properly
- I'm missing widgets in the UI. Lets say you have a 'Text' SDC component and you gave it a 'text color' property (which will add a bootstrap color class to your text element). At the moment it will just be a dropdown where you select the color name. It would be nice to have a color widget to select a color. Or a slider widget for example to select a padding or margin class. They are working in it though.
- The multilanguage problem: When I added a language (my project now has Dutch as default language, and English as a second language) then the canvas page link automatically became '/nl/canvas/editor/canvas_page/6' instead of '/canvas/editor/canvas_page/6'. Sounds logical except the /LANGCODE/canvas/editor/canvas_page/PAGEID does not work. So I wrote some code that converts canvas links and removes the language part. When creating/editing a page, there is now a 'Language' dropdown. So you can set the language of the page. But actually translating a page does not work for me at the moment
- Currently you can not create a menulink directly from the canvas create/edit page. But menulinks do work if you create them via Structure -> Menus.

Probably TMI, but you can actually use Canvas for monolingual sites right now.

As for the question about creating an MVP: I'm sorry but I have already gone for just creating a very basic custom module 'canvas_sitemap' for now. It has a routing file:

canvas_sitemap.sitemap:
  path: '/sitemap.xml'
  defaults:
    _controller: 'Drupal\canvas_sitemap\Controller\SitemapController::generateSitemap'
    _disable_route_normalizer: 'TRUE'
    _title: 'Sitemap'
  requirements:
    # Sitemaps are accessible for everyone.
    _access: 'TRUE'

And a controller:

<?php

namespace Drupal\canvas_sitemap\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a controller for generating a sitemap.xml file.
 */
class SitemapController extends ControllerBase {

  /**
   * The entity type manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The language manager service.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * Constructs a new SitemapController object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager service.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager service.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $language_manager) {
    $this->entityTypeManager = $entity_type_manager;
    $this->languageManager = $language_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('language_manager'),
    );
  }

  /**
   * Generates a sitemap.xml file for canvas pages.
   *
   * @return \Symfony\Component\HttpFoundation\Response
   *   A response object containing the sitemap.xml content.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
   *   If the current domain or language is not valid.
   */
  public function generateSitemap() {

    // Query published sitemap pages.
    $pages = \Drupal::entityTypeManager()->getStorage('canvas_page')->loadByProperties(['status' => 1]);
    // @TODO: langocode.
    foreach ($pages as $page) {
      // Create a URL object from the entity route.
      $url_object = Url::fromRoute('entity.canvas_page.canonical', ['canvas_page' => $page->id()], ['absolute' => TRUE]);
      // Convert the URL object to a string.
      $url_string = $url_object->toString();
      // Get the date when node was last changed.
      $timestamp = $page->get('changed')->value;
      $date = DrupalDateTime::createFromTimestamp($timestamp);
      $date_changed = $date->format('c');
      // Add the url string to the sitemap.
      $entries[] = "<url>
      <loc>$url_string</loc>
      <lastmod>$date_changed</lastmod>
      <priority>0.5</priority>
      </url>";
      // You can also add other elements such as <lastmod>, <changefreq> or <priority> if you want.
      // See https://www.sitemaps.org/protocol.html for more details.
    }

    // Generate the sitemap.xml content by concatenating the entries with the XML header and footer.
    $styling_file = '/modules/custom/canvas_sitemap/assets/sitemap-styling.xsl';
    $content = '<?xml version="1.0" encoding="UTF-8"?>';
    $content .= "<?xml-stylesheet type='text/xsl' href='$styling_file'?>";
    $content .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
    $content .= implode('', $entries);
    $content .= '</urlset>';

    // Create and return a response object with the content and the XML header.
    return new Response($content, Response::HTTP_OK, ['Content-Type' => 'application/xml']);
  }

}

I also have a sitemap-styling.xsl file that gets included so the sitemap visually looks nice (see screenshot). Maybe that's something the simple_sitemap module could do too.

gbyte’s picture

Category: Feature request » Support request
Status: Active » Fixed

I like your maker energy, but that's a bit of not-invented-here of you. This here module specializes in creating sitemaps for esoteric use cases; you could have added a URL generator plugin and left all other logic to the module. Another possibility would be to implement hook_simple_sitemap_arbitrary_links_alter() and add any links into it. See extending the module.

But more importantly while writing the above, I realized the module may already support "canvas_page" given it's a simple content entity so I installed canvas, created a page and checked. You won't like this bit (given you put all the effort in): Canvas pages are already fully compatible with the module.

  • Go to /admin/config/search/simplesitemap/entities
  • Enable "Page"
  • Configure it.

What seems to be broken is overriding sitemap settings on the canvas page UI. May create an issue later.

Regarding sitemap styling: That's in (albeit not as nice as yours); I believe sorting is broken right now because of the missing jQuery. There is an issue.

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.

flyke’s picture

I actually really like this bit :-)
Thank you for explaining how to use the simple_sitemap module for canvas pages, I am absolutely going to use that in favor of the custom module. That was always meant as a stop gap until I figured out the best contrib solution, which there already was apparently.

flyke’s picture

Status: Fixed » Closed (works as designed)

Thank you for the walkthrough, everything works as expected and I can indeed successfully create sitemaps for canvas pages.

gbyte’s picture

Status: Closed (works as designed) » Fixed

This has been converted to a support request, hence fixed.

Happy to hear!

Status: Fixed » Closed (fixed)

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