From facfab07adf19daca94755b6ae4b89202c77859d Mon Sep 17 00:00:00 2001 From: Chris Herold Date: Wed, 17 May 2023 11:22:43 -0700 Subject: [PATCH 1/2] preview mode updates --- .../src/lib/wordpress/graphql/queryContent.js | 6 +- website/src/lib/wordpress/index.js | 85 ++++++------------- website/src/pages/[[...slug]].js | 18 ++-- website/src/pages/api/preview.js | 35 ++------ .../setup/helpers/headless-redirect.php | 29 +------ 5 files changed, 49 insertions(+), 124 deletions(-) diff --git a/website/src/lib/wordpress/graphql/queryContent.js b/website/src/lib/wordpress/graphql/queryContent.js index 1174049..0963010 100644 --- a/website/src/lib/wordpress/graphql/queryContent.js +++ b/website/src/lib/wordpress/graphql/queryContent.js @@ -4,10 +4,12 @@ import { flexWysiwygContent } from './flexWysiwygContent'; import pageOptions from './fragmentPageOptions'; import seo from './fragmentSeo'; -export function queryContent(draft) { +export function queryContent(draft, options) { const query = /* GraphQL */ ` query GetContent($slug: ID!, $preview: Boolean) { - contentNode(id: $slug, idType: URI, asPreview: $preview) { + contentNode(id: $slug, idType: ${ + options?.uriType ?? 'URI' + }, asPreview: $preview) { __typename id databaseId diff --git a/website/src/lib/wordpress/index.js b/website/src/lib/wordpress/index.js index ab48401..6f88bb0 100644 --- a/website/src/lib/wordpress/index.js +++ b/website/src/lib/wordpress/index.js @@ -1,5 +1,6 @@ import fetch from 'isomorphic-unfetch'; import { WORDPRESS_API_URL } from 'lib/constants'; +import { trimLeadingSlash } from 'lib/utils'; import { queryContent } from './graphql/queryContent'; import { queryGlobals } from './graphql/queryGlobals'; import { queryPosts } from './graphql/queryPosts'; @@ -36,32 +37,6 @@ async function fetchAPI(query, { variables } = {}, token) { return json.data; } -/** - * Get post types and paths for preview mode redirects. - */ -export async function getContentTypes(token) { - const query = /* GraphQL */ ` - query ContentTypes { - contentTypes { - nodes { - name - restBase - } - } - } - `; - - const data = await fetchAPI( - query, - { - variables: { preview: true }, - }, - token, - ); - - return data?.contentTypes?.nodes; -} - /** * To assist with Preview Mode, this will grab status for content by DB id * (needed for revisions, unpublished content) @@ -77,6 +52,7 @@ export async function getPreviewContent( uri status databaseId + previewRevisionDatabaseId contentType { node { name @@ -156,45 +132,34 @@ export async function getNodeType(slug) { /** * Get fields for single page regardless of post type. */ -export async function getContent(slug, preview, previewData) { +export async function getContent( + slug, + preview, + previewData, + options, +) { let draft = false; if (preview) { - // Get the content types to help build preview URLs - const contentTypesArray = await getContentTypes( - previewData?.token, - ); - const contentTypes = {}; - - for (const contentType of contentTypesArray) { - contentTypes[contentType.restBase] = contentType.name; - } - - // Because static pages can't support query strings and those - // make preview mode much easier across published statuses and post types - // this coerces any numeric slug in preview mode to an ID and assumes post type - const segments = slug.split('/'); - const lastSegment = segments[segments.length - 1]; - const secondLastSegment = - segments.length > 2 ? segments[segments.length - 2] : null; - // Get post type URL segment - const postType = contentTypes[secondLastSegment]; - - // wordpress requires a different slug structure for various post types - if (slug !== '/' && !isNaN(Number(lastSegment))) { - draft = true; - if (postType === 'post') { - slug = `/?p=${lastSegment}`; - } else if (secondLastSegment) { - slug = `/?id=${lastSegment}&post_type=${postType}`; - } else { - slug = `/?page_id=${lastSegment}`; - } - } else if (slug !== '/') { - slug += '?preview=true'; + // This is based on Next.js wordpress example: https://github.com/vercel/next.js/blob/canary/examples/cms-wordpress/lib/api.ts#L105-L112 + // If the preview is for a draft or a revision, we need to query by ID. + // We check to see if the preview data is for the same post as the slug + // and if it is, we set `slug` to the ID of the post and the `uriType` to `DATABASE_ID`. + const postPreview = previewData?.post; + const trimSlug = trimLeadingSlash(slug); + const isId = Number.isInteger(Number(trimSlug)); + const isSamePost = isId && Number(trimSlug) === postPreview?.id; + const isDraft = isSamePost && postPreview?.status === 'draft'; + const isRevision = + isSamePost && postPreview?.status === 'publish'; + + if ((isDraft || isRevision) && postPreview?.id) { + draft = isDraft; + slug = postPreview.id; + options.uriType = 'DATABASE_ID'; } } - let query = queryContent(draft); + let query = queryContent(draft, options); const data = await fetchAPI( query, diff --git a/website/src/pages/[[...slug]].js b/website/src/pages/[[...slug]].js index 035c8f4..084eb91 100644 --- a/website/src/pages/[[...slug]].js +++ b/website/src/pages/[[...slug]].js @@ -89,14 +89,16 @@ export async function getStaticProps({ return { redirect: redirect }; } - // Check nodeType before assuming it's a contentNode. We 404 on nonsupported types, but you could handle. - const { nodeByUri } = await getNodeType(slug); - if (!nodeByUri?.isContentNode) { - return { - notFound: true, - revalidate: 60, - props: {}, - }; + if (!preview) { + // Check nodeType before assuming it's a contentNode. We 404 on nonsupported types, but you could handle. + const { nodeByUri } = await getNodeType(slug); + if (!nodeByUri?.isContentNode) { + return { + notFound: true, + revalidate: 60, + props: {}, + }; + } } const data = await getContent(slug, preview, previewData); diff --git a/website/src/pages/api/preview.js b/website/src/pages/api/preview.js index f025409..801e391 100644 --- a/website/src/pages/api/preview.js +++ b/website/src/pages/api/preview.js @@ -1,11 +1,11 @@ import { authorize } from 'lib/auth'; -import { getContentTypes, getPreviewContent } from 'lib/wordpress'; +import { getPreviewContent } from 'lib/wordpress'; const COOKIE_MAX_AGE = 86400; export default async function preview(req, res) { let accessToken; - const { code, id, preview_id, path, slug } = req.query; + const { code, id, path, slug } = req.query; // Get Auth Token if (code) { @@ -40,7 +40,7 @@ export default async function preview(req, res) { // Fetch WordPress to check if the provided `id` exists const post = await getPreviewContent( - preview_id || id, + id, 'DATABASE_ID', accessToken, ); @@ -50,20 +50,14 @@ export default async function preview(req, res) { return res.status(401).json({ message: 'Post not found' }); } - // Get the content types to help build preview URLs - const contentTypesArray = await getContentTypes(accessToken); - const contentTypes = {}; - - for (const contentType of contentTypesArray) { - contentTypes[contentType.name] = contentType.restBase; - } + const postId = post?.previewRevisionDatabaseId || post?.databaseId; // Enable Preview Mode by setting the cookies res.setPreviewData( { post: { uri: post.uri, - id: post.databaseId, + id: postId, status: post.status, type: post.contentType.node.name, }, @@ -74,24 +68,9 @@ export default async function preview(req, res) { }, ); - let Location = post.uri; - const typePath = contentTypes[post.contentType.node.name]; - - // Draft posts need a little help pointing towards the correct Next.js page template - if ( - post.status === 'draft' && - post.contentType.node.name !== 'page' - ) { - Location = `/${typePath}/${post.databaseId}`; - } else if (post.status === 'draft') { - Location = `/${post.databaseId}`; - } else if (preview_id && post.contentType.node.name !== 'page') { - Location = `/${typePath}/${preview_id}`; - } else if (preview_id || slug || path) { - Location = `/${preview_id || slug || path}`; - } + const location = `/${postId}/`; // Redirect to the path from the fetched post - res.writeHead(307, { Location }); + res.writeHead(307, { location }); return res.end(); } diff --git a/wordpress/wp-content/themes/headless/setup/helpers/headless-redirect.php b/wordpress/wp-content/themes/headless/setup/helpers/headless-redirect.php index 316da8e..a9ddcb5 100644 --- a/wordpress/wp-content/themes/headless/setup/helpers/headless-redirect.php +++ b/wordpress/wp-content/themes/headless/setup/helpers/headless-redirect.php @@ -33,46 +33,23 @@ function headless_redirect(){ // if so, redirect to preview path if ( is_preview() ) { if ( current_user_can( 'edit_posts' ) ) { - $revisions = wp_get_post_revisions( - $id, - [ - 'posts_per_page' => 1, - 'fields' => 'ids', - 'check_enabled' => false, - ] - ); $auth_code = wpe_headless_generate_authentication_code( wp_get_current_user() ); - $preview_id = is_array( $revisions ) && ! empty( $revisions ) ? array_values( $revisions )[0] : null; + $redirect = $headless_domain . '/api/preview/?code=' . rawurlencode($auth_code) . '&id=' . $id; - $redirect = $headless_domain . '/api/preview/?code=' . rawurlencode($auth_code) . '&id=' . $id . '&preview_id=' . $preview_id; return $redirect; } } // else do standard redirect tree if ($slug) { - if ( current_user_can( 'edit_posts' ) ) { - $auth_code = wpe_headless_generate_authentication_code( - wp_get_current_user() - ); - $redirect = $headless_domain . '/api/preview/?code=' . rawurlencode($auth_code) . '&slug=' . $slug . '&id=' . $id; - } else { - $redirect = $headless_domain . $slug; - } + $redirect = $headless_domain . $slug; } else { $path = $_SERVER['REQUEST_URI']; - if ( current_user_can( 'edit_posts' ) ) { - $auth_code = wpe_headless_generate_authentication_code( - wp_get_current_user() - ); - $redirect = $headless_domain . '/api/preview/?code=' . rawurlencode($auth_code) . '&path=' . $path . '&id=' . $id; - } else { - $redirect = $headless_domain . $path; - } + $redirect = $headless_domain . $path; } return $redirect; From 2fc56c3b77b2cdccc742001c74f2650fffb418d8 Mon Sep 17 00:00:00 2001 From: Cameron Corda Date: Mon, 19 Jun 2023 10:50:30 -0700 Subject: [PATCH 2/2] preview mode undefined options solve --- website/src/lib/wordpress/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/lib/wordpress/index.js b/website/src/lib/wordpress/index.js index 6f88bb0..39aab7a 100644 --- a/website/src/lib/wordpress/index.js +++ b/website/src/lib/wordpress/index.js @@ -136,7 +136,7 @@ export async function getContent( slug, preview, previewData, - options, + options = {}, ) { let draft = false; if (preview) {