Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: preview pages #1027

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2d27234
fix: preview pages
andrewgolovanov Sep 21, 2023
485f382
fix: minor changes
andrewgolovanov Sep 21, 2023
1498d88
test: draft mode
andrewgolovanov Sep 21, 2023
582cfc3
test: draft mode
andrewgolovanov Sep 21, 2023
17e3186
test: searchParams
andrewgolovanov Sep 21, 2023
e390779
test: searchParams
andrewgolovanov Sep 21, 2023
dbb47ea
test: searchParams
andrewgolovanov Sep 21, 2023
a29bc57
test: searchParams
andrewgolovanov Sep 21, 2023
2cdb0ae
fix: minor changes
andrewgolovanov Sep 21, 2023
029cdbf
chore: return revalidate
andrewgolovanov Sep 21, 2023
5b33b84
test: searchParams
andrewgolovanov Sep 22, 2023
74ede5f
chore: add small adjustments
andrewgolovanov Sep 22, 2023
5666dc8
Merge branch 'main' of https://github.com/neondatabase/website into f…
andrewgolovanov Nov 22, 2023
9cdc228
feat: disable draftMode checking for unpublished pages
andrewgolovanov Nov 22, 2023
4f55276
Merge branch 'main' into fix-wp-preview
vannyle Dec 7, 2023
2661a61
Merge branch 'main' into fix-wp-preview
vannyle Feb 9, 2024
c75b76d
Merge branch 'main' into fix-wp-preview
vannyle Feb 9, 2024
9834adb
Merge branch 'main' into fix-wp-preview
yasell Apr 3, 2024
f08678a
Merge branch 'main' into fix-wp-preview
yasell Apr 9, 2024
b302c07
feat: add dynamic page to preview
yasell Apr 9, 2024
d81ed53
chore: trigger rebuild
yasell Apr 9, 2024
193a08d
Merge remote-tracking branch 'origin/main' into fix-wp-preview
saimonkat Jun 6, 2024
b2f2781
fix: add eslint-disable rule for react/prop-types
saimonkat Jun 6, 2024
54eaf75
feat: update landing page
saimonkat Jun 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,12 @@ const defaultConfig = {
},
{
source: '/demos/regional-latency',
destination: 'https://latencies-ui.vercel.app/demos/regional-latency'
destination: 'https://latencies-ui.vercel.app/demos/regional-latency',
},
{
source: '/demos/regional-latency/:asset*',
destination: 'https://latencies-ui.vercel.app/demos/regional-latency/:asset*'
}
destination: 'https://latencies-ui.vercel.app/demos/regional-latency/:asset*',
},
];
},
webpack(config) {
Expand Down
27 changes: 24 additions & 3 deletions src/app/[slug]/page.jsx → src/app/(wp-pages)/[slug]/page.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/* eslint-disable react/no-unstable-nested-components */
/* eslint-disable react/prop-types */
import { draftMode } from 'next/headers';
import { notFound } from 'next/navigation';

import PreviewWarning from 'components/pages/blog-post/preview-warning';
import Hero from 'components/pages/landing/hero';
import CTA from 'components/pages/pricing/cta';
import Container from 'components/shared/container';
Expand All @@ -12,7 +14,12 @@ import replicasIcon from 'icons/landing/replica.svg';
import scaleIcon from 'icons/landing/scalability.svg';
import storageIcon from 'icons/landing/storage.svg';
import timerIcon from 'icons/landing/timer.svg';
import { getLandingPages, getWpPageBySlug, getStaticPages } from 'utils/api-pages';
import {
getLandingPages,
getWpPageBySlug,
getStaticPages,
getWpPreviewPageData,
} from 'utils/api-pages';
import { getHubspotFormData } from 'utils/forms';
import getMetadata from 'utils/get-metadata';
import getReactContentWithLazyBlocks from 'utils/get-react-content-with-lazy-blocks';
Expand All @@ -24,8 +31,21 @@ const icons = {
replicas: replicasIcon,
};

const DynamicPage = async ({ params }) => {
const page = await getWpPageBySlug(params.slug);
const DynamicPage = async ({ params, searchParams }) => {
const { isEnabled: isDraftModeEnabled } = draftMode();

let pageResult;

// TODO: this is a temporary fix for a known problem with accessing serachParams on the Vercel side - https://github.com/vercel/next.js/issues/54507
await Promise.resolve(JSON.stringify(searchParams));

if (isDraftModeEnabled) {
pageResult = await getWpPreviewPageData(searchParams?.id, searchParams?.status);
} else {
pageResult = await getWpPageBySlug(params.slug);
}

const page = pageResult;

if (!page) return notFound();

Expand Down Expand Up @@ -80,6 +100,7 @@ const DynamicPage = async ({ params }) => {
</Container>
</article>
)}
{isDraftModeEnabled && <PreviewWarning />}
</Layout>
);
};
Expand Down
122 changes: 122 additions & 0 deletions src/app/(wp-pages)/wp-draft-post-preview-page/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/* eslint-disable react/no-unstable-nested-components */
/* eslint-disable react/prop-types */
import { notFound } from 'next/navigation';

import PreviewWarning from 'components/pages/blog-post/preview-warning';
import Hero from 'components/pages/landing/hero';
import CTA from 'components/pages/pricing/cta';
import Container from 'components/shared/container';
import Content from 'components/shared/content';
import Layout from 'components/shared/layout';
import SplitViewGrid from 'components/shared/split-view-grid';
import LINKS from 'constants/links';
import SEO_DATA from 'constants/seo-data';
import replicasIcon from 'icons/landing/replica.svg';
import scaleIcon from 'icons/landing/scalability.svg';
import storageIcon from 'icons/landing/storage.svg';
import timerIcon from 'icons/landing/timer.svg';
import { getWpPreviewPageData } from 'utils/api-pages';
import { getHubspotFormData } from 'utils/forms';
import getMetadata from 'utils/get-metadata';
import getReactContentWithLazyBlocks from 'utils/get-react-content-with-lazy-blocks';

const icons = {
scale: scaleIcon,
timer: timerIcon,
storage: storageIcon,
replicas: replicasIcon,
};

/*
NOTE:
This page is only needed to show previews for the drafts.
Its code is identical to the wp-pages page template, except for the data fetching.
If you need to change something here, сhange it first in the wp-pages page
and then copy the changes here.
*/
/*
WARNING:
You can't have a page in Wordpress with the "wp-draft-post-preview-page" slug. Please be careful.
*/
const WpPageDraft = async ({ searchParams }) => {
// TODO: this is a temporary fix for a known problem with accessing serachParams on the Vercel side - https://github.com/vercel/next.js/issues/54507
await Promise.resolve(JSON.stringify(searchParams));

if (!searchParams?.id || !searchParams?.status) {
return notFound();
}

const page = await getWpPreviewPageData(searchParams?.id, searchParams?.status);

if (!page) return notFound();

const {
title,
content,
template: { templateName },
} = page;

const contentWithLazyBlocks = getReactContentWithLazyBlocks(
content,
{
landinghero: async ({ hubspotFormId, ...restProps }) => {
const formData = await getHubspotFormData(hubspotFormId);
return <Hero formData={formData} hubspotFormId={hubspotFormId} {...restProps} />;
},
landingfeatures: ({ features, ...restProps }) => {
const items = features.map((feature) => {
const icon = icons[feature.iconName];
return {
...feature,
icon,
};
});

return (
<SplitViewGrid
className="mx-auto mb-32 mt-16 max-w-[1265px] lg:my-14"
{...restProps}
items={items}
size="sm"
isGradientLabel
/>
);
},
landingcta: CTA,
},
true
);

return (
<Layout>
{templateName === 'Landing' ? (
contentWithLazyBlocks
) : (
<article className="safe-paddings py-48 3xl:py-44 2xl:py-40 xl:py-32 lg:pb-24 lg:pt-12 md:pb-20 md:pt-6">
<Container size="xs">
<h1 className="t-5xl font-title font-semibold">{title}</h1>
</Container>
<Container size="xs">
<Content className="prose-static mt-8 2xl:mt-7 xl:mt-6" content={content} asHTML />
</Container>
</article>
)}
<PreviewWarning />
</Layout>
);
};

export async function generateMetadata() {
const { title, description, imagePath } = SEO_DATA.blog;

return getMetadata({
title,
description,
keywords: '',
robotsNoindex: 'noindex',
pathname: `${LINKS.blog}/wp-draft-post-preview-page`,
imagePath,
});
}

export default WpPageDraft;
10 changes: 7 additions & 3 deletions src/app/api/preview/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ export async function GET(request) {
return new Response('Invalid token', { status: 401 });
}

if (postType !== 'post') {
return new Response('Preview functionality only works for blog posts', { status: 401 });
if (postType !== 'post' && postType !== 'page') {
return new Response('Preview functionality only works for blog posts and pages', {
status: 401,
});
}

draftMode().enable();
Expand All @@ -31,5 +33,7 @@ export async function GET(request) {

const slug = permalink && postStatus === 'publish' ? permalink : 'wp-draft-post-preview-page';

redirect(`/blog/${slug}?${redirectSearchParams.toString()}`);
postType === 'page'
? redirect(`/${slug}?${redirectSearchParams.toString()}`)
: redirect(`/blog/${slug}?${redirectSearchParams.toString()}`);
}
3 changes: 3 additions & 0 deletions src/app/blog/[slug]/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const BlogPage = async ({ params, searchParams }) => {

let postResult;

// TODO: this is a temporary fix for a known problem with accessing serachParams on the Vercel side - https://github.com/vercel/next.js/issues/54507
await Promise.resolve(JSON.stringify(searchParams));

if (isDraftModeEnabled) {
postResult = await getWpPreviewPostData(searchParams?.id, searchParams?.status);
} else {
Expand Down
1 change: 0 additions & 1 deletion src/components/shared/button/button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import Link from 'components/shared/link';
import getNodeText from 'utils/get-node-text';
import sendGtagEvent from 'utils/send-gtag-event';


const styles = {
base: 'inline-flex items-center justify-center font-bold !leading-none text-center whitespace-nowrap rounded-full transition-colors duration-200 outline-none',
size: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function extractTextFromNode(node) {
});
return text;
}

// If there's only one child, process that child directly.
return extractTextFromNode(node.props.children);
}
Expand Down
64 changes: 62 additions & 2 deletions src/utils/api-pages.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { fetchGraphQL, gql, graphQLClient } from 'lib/graphQLClient';
import { fetchGraphQL, gql, graphQLClient, graphQLClientAdmin } from 'lib/graphQLClient';

import getAuthToken from './api-auth';

const PAGE_SEO_FRAGMENT = gql`
fragment wpPageSeo on Page {
Expand Down Expand Up @@ -72,6 +74,64 @@ const getWpPageBySlug = async (slug) => {
return data?.page;
};

const getWpPreviewPageData = async (id, status) => {
const {
refreshJwtAuthToken: { authToken },
} = await getAuthToken();

const isDraft = status === 'draft';
const isRevision = status === 'publish';
let query;

if (isDraft) {
query = gql`
query wpPageById($id: ID!) {
page(id: $id, idType: DATABASE_ID) {
content(format: RENDERED)
title(format: RENDERED)
template {
templateName
}
...wpPageSeo
}
}
${PAGE_SEO_FRAGMENT}
`;

const data = await graphQLClientAdmin(authToken).request(query, { id });

return data?.page;
}

if (isRevision) {
query = gql`
query wpPageById($id: ID!) {
page(id: $id, idType: DATABASE_ID) {
revisions(first: 1, where: { orderby: { field: MODIFIED, order: DESC } }) {
edges {
page: node {
content(format: RENDERED)
title(format: RENDERED)
template {
templateName
}
}
}
}
...wpPageSeo
}
}
${PAGE_SEO_FRAGMENT}
`;

const revisionPageData = await graphQLClientAdmin(authToken).request(query, { id });

console.log(revisionPageData?.page.revisions?.edges[0]);

return revisionPageData?.page.revisions?.edges[0].page;
}
};

const getAboutPage = async () => {
const aboutPageQuery = gql`
query aboutPage {
Expand All @@ -87,4 +147,4 @@ const getAboutPage = async () => {
return data?.page;
};

export { getLandingPages, getStaticPages, getWpPageBySlug, getAboutPage };
export { getLandingPages, getStaticPages, getWpPageBySlug, getAboutPage, getWpPreviewPageData };