chapter-three / next-drupal

Next.js for Drupal has everything you need to build a next-generation front-end for your Drupal site: SSG, SSR, and ISR, Multi-site, Authentication, Webforms, Search API, I18n and Preview mode (works with JSON:API and GraphQL).
https://next-drupal.org
MIT License
639 stars 178 forks source link

Support Drupal's preview mode #132

Open Elendev opened 2 years ago

Elendev commented 2 years ago

The routes are currently hard-coded in the HTMLRenderer: https://github.com/chapter-three/next-drupal/blob/691a4b8bcf747b13e908c3dc4423ff168128d430/modules/next/src/Render/MainContent/HtmlRenderer.php#L98-L103

We should be able to make it configurable (hook? Settings form?) to be able to add preview URLs.

The previews can be made available in the API with the help of the module https://www.drupal.org/project/jsonapi_node_preview.

shadcn commented 2 years ago

Yep. I had to edit this directly for this demo: https://twitter.com/shadcn/status/1491853030396141568

This could be handled in the NextPreviewer plugin or per entity type to be more flexible.

Let's see.

shadcn commented 2 years ago

+1 for configurable per entity type.

Elendev commented 2 years ago

We've been able to make the Drupal preview work on our project, but for that we had to do some important changes in the way the module works.

The main change is that we don't use the slug anymore for preview (either for revisions, or for the view of the node), but instead the URL for Next's preview mode contains the Entity type, the Entity bundle and the UUID.

@shadcn all the changes below have been reported on NextJS's side too. Do you think some of those changes, or at least the flexibility required, can be added to the module? Would you accept such a pull request, or do you think the logic below has to be adapted?

HtmlRenderer

We've replaced the HtmlRenderer to add the "entity.$entity_type_id.preview" route.

Iframe

We made a custom iFrame plugin that provides the uuid, entityType and entityBundle.

We only provide the slug when the entity exists: if it's a new entity (example: click on the preview button during creation of the entity, before first save), the toUrl() return an error since the entity doesn't have an ID. The simple version:

    if (!$entity->isNew()) {
      $entityPath = '/' . $entity->toUrl()->getInternalPath();
      $query['slug'] = $this->pathAliasManager->getAliasByPath($entityPath, $entity->language()->getId());
    }

For that we had to entirely replace the way the URL is generated, and we currently don't use the NextSite::getPreviewUrlForEntity method anymore.

A preview parameter is added to the NextJS URL to specify that the API endpoint is not the same one (it's not /jsonapi/node/page/{uuid}, it's /jsonapi/node/page/{uuid}/preview, and is calculated this way: $isPreview = $this->routeMatch->getRouteName() === 'entity.' . $entity->getEntityTypeId() . '.preview';

shadcn commented 2 years ago

@Elendev This looks similar to the changes I had to do to make the POC work (regarding the handling of slug for the entity).

all the changes below have been reported on NextJS's side too

Can you link me to the issue please?

If you would like to work on this, I'd be happy to review and collab. Let's open a PR and hash out a way forward.

Appreciate all the help you're putting into making the project better.

Thank you

Elendev commented 2 years ago

Can you link me to the issue please?

@shadcn sorry I haven't been clear, we have reported those changes on our NextJS by bypassing the existing package. I'll see with my colleague if it's easy to re-integrate in the base module.

In the meantime, I'll find time to propose some PR with improvements to allow more flexibility, and in the end be able to include the preview capability directly in the module 👍

fiasco commented 2 years ago

In Acquia CMS we want two modes of headless operation:

When next.js site preview is enabled, it doesn't work in pure headless mode because Drupal is no longer using the HtmlRenderer to render the Drupal view. It also doesn't work in hybrid mode because it overtakes the render Drupal should be rendering.

Instead we've implemented site preview as a local task to a node and rendered it inside its own tab. This at least makes it work in pure headless mode but we'd need to be able to turn the HtmlRenderer off in hybrid mode to create an operable experience.

Happy to contribute our changes to this project rather than manage them ourselves if they make sense for this project.

shadcn commented 2 years ago

@fiasco I see. This has been discussed here: #217

Let's hash this out on the other issue?

(This issue here is for adding support for https://www.drupal.org/project/jsonapi_node_preview)

Thanks

dottodot commented 1 year ago

Graphql Compose is adding support for previews and Revisions https://drupal-graphql-compose.github.io/documentation/#/features/previews-revisions so would be good to make it compatible with that too.