Skip to content

[PCC 2080] Add support for draft publishing level and versionIds #366

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 11 additions & 3 deletions packages/core/src/core/pantheon-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import {
PCCConvenienceFunctions,
} from "../helpers";
import { parseJwt } from "../lib/jwt";
import { Article, MetadataGroup, Site, SmartComponentMap } from "../types";
import {
Article,
MetadataGroup,
Site,
SmartComponentMap,
type PublishingLevel,
} from "../types";
import { PantheonClient, PantheonClientConfig } from "./pantheon-client";

export interface ApiRequest {
Expand Down Expand Up @@ -111,7 +117,7 @@ const defaultOptions = {
notFoundPath: "/404",
} satisfies PantheonAPIOptions;

type AllowablePublishingLevels = "PRODUCTION" | "REALTIME" | undefined;
type AllowablePublishingLevels = keyof typeof PublishingLevel | undefined;

export const PantheonAPI = (givenOptions?: PantheonAPIOptions) => {
const options = {
Expand All @@ -124,7 +130,7 @@ export const PantheonAPI = (givenOptions?: PantheonAPIOptions) => {
await res.setHeader("Access-Control-Allow-Origin", "*");

const { command: commandInput, pccGrant, ...restOfQuery } = req.query;
const { publishingLevel } = restOfQuery;
const { publishingLevel, versionId } = restOfQuery;

if (!commandInput) {
return await res.redirect(302, options?.notFoundPath || "/404");
Expand Down Expand Up @@ -197,6 +203,7 @@ export const PantheonAPI = (givenOptions?: PantheonAPIOptions) => {
publishingLevel: publishingLevel
?.toString()
.toUpperCase() as AllowablePublishingLevels,
versionId: versionId?.toString(),
},
),
client && !client.apiKey?.startsWith("pcc_grant")
Expand All @@ -213,6 +220,7 @@ export const PantheonAPI = (givenOptions?: PantheonAPIOptions) => {
const queryParams = {
pccGrant: pccGrant?.toString(),
publishingLevel: publishingLevel?.toString().toUpperCase(),
versionId: versionId?.toString(),
};

return await res.redirect(
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/helpers/articles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface ArticleQueryArgs {
sortOrder?: keyof typeof SortOrder;
metadataFilters?: { [key: string]: unknown };
preamble?: string;
versionId?: string;
}

export interface ArticlePaginatedQueryArgs {
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/helpers/convenience.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,15 @@ async function getAllArticlesWithSummary(

async function getArticleBySlugOrId(
id: number | string,
publishingLevel: "PRODUCTION" | "REALTIME" = "PRODUCTION",
args?: Parameters<typeof _getArticleBySlugOrId>[2],
) {
const post = await _getArticleBySlugOrId(
buildPantheonClient({ isClientSide: false }),
id,
{
publishingLevel,
publishingLevel: "PRODUCTION",
contentType: "TREE_PANTHEON_V2",
...args,
},
);

Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/lib/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ export const GET_ARTICLE_QUERY = gql`
$slug: String
$contentType: ContentType
$publishingLevel: PublishingLevel
$versionId: String
) {
article(
id: $id
slug: $slug
contentType: $contentType
publishingLevel: $publishingLevel
versionId: $versionId
) {
id
title
Expand All @@ -34,11 +36,13 @@ export const ARTICLE_UPDATE_SUBSCRIPTION = gql`
$id: String!
$contentType: ContentType
$publishingLevel: PublishingLevel
$versionId: String
) {
article: articleUpdate(
id: $id
contentType: $contentType
publishingLevel: $publishingLevel
versionId: $versionId
) {
id
title
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export type PaginatedArticle = {
export enum PublishingLevel {
PRODUCTION = "PRODUCTION",
REALTIME = "REALTIME",
DRAFT = "DRAFT",
}

export enum ContentType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ export async function GET(request: NextRequest) {
articles = await Promise.all(
docIds.map(async (id) => {
try {
return await PCCConvenienceFunctions.getArticleBySlugOrId(
id,
"PRODUCTION",
);
return await PCCConvenienceFunctions.getArticleBySlugOrId(id);
} catch (error) {
const sanitizedId = id.replace(/\n|\r/g, "");
console.error(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import {
import {
getArticlePathComponentsFromContentStructure,
PCCConvenienceFunctions,
getArticlePathComponentsFromContentStructure
} from "@pantheon-systems/pcc-react-sdk/server";
type PublishingLevel,
} from "@pantheon-systems/pcc-react-sdk/server";
import { cookies } from "next/headers";
import { notFound, redirect, RedirectType } from "next/navigation";
import queryString from "query-string";
import { pantheonAPIOptions } from "../../api/pantheoncloud/[...command]/api-options";
import { ClientsideArticleView } from "./clientside-articleview";


export interface ArticleViewProps {
params: { uri: string[] };
searchParams: {
publishingLevel: "PRODUCTION" | "REALTIME";
publishingLevel: keyof typeof PublishingLevel;
pccGrant: string | undefined;
versionId: string | undefined;
};
}

Expand All @@ -26,14 +27,22 @@ export const ArticleView = async ({
searchParams,
});

return <ClientsideArticleView article={article} grant={grant || undefined} />;
return (
<ClientsideArticleView
article={article}
grant={grant || undefined}
publishingLevel={searchParams.publishingLevel}
versionId={searchParams.versionId || null}
/>
);
};

interface GetServersideArticleProps {
params: { uri: string[] };
searchParams: {
publishingLevel: "PRODUCTION" | "REALTIME";
publishingLevel: keyof typeof PublishingLevel;
pccGrant: string | undefined;
versionId: string | undefined;
};
}

Expand All @@ -42,26 +51,25 @@ export async function getServersideArticle({
searchParams,
}: GetServersideArticleProps) {
const { uri } = params;
const { publishingLevel, pccGrant, ...query } = searchParams;
const { publishingLevel, pccGrant, versionId, ...query } = searchParams;

const slugOrId = uri[uri.length - 1];
const grant = pccGrant || cookies().get("PCC-GRANT")?.value || null;

// Fetch the article and site in parallel
const [article, site] = await Promise.all([
PCCConvenienceFunctions.getArticleBySlugOrId(
slugOrId,
(publishingLevel?.toString().toUpperCase() as "PRODUCTION" | "REALTIME") ||
"PRODUCTION",
),
PCCConvenienceFunctions.getArticleBySlugOrId(slugOrId, {
publishingLevel,
versionId,
}),
PCCConvenienceFunctions.getSite(),
]);

if (!article) {
return notFound();
}

// Get the article path from the content structure
// Get the article path from the content structure
const articlePath = getArticlePathComponentsFromContentStructure(
article,
site,
Expand All @@ -70,12 +78,12 @@ export async function getServersideArticle({
if (
// Check if the article has a slug
((article.slug?.trim().length &&
// Check if the slug is not the same as the slugOrId
article.slug.toLowerCase() !== slugOrId?.trim().toLowerCase())||
// Check if the article path is not the same as the uri
articlePath.length !== uri.length - 1 ||
// Check if the article path (with all the components together) is not the same as the uri
articlePath.join("/") !== uri.slice(0, -1).join("/")) &&
// Check if the slug is not the same as the slugOrId
article.slug.toLowerCase() !== slugOrId?.trim().toLowerCase()) ||
// Check if the article path is not the same as the uri
articlePath.length !== uri.length - 1 ||
// Check if the article path (with all the components together) is not the same as the uri
articlePath.join("/") !== uri.slice(0, -1).join("/")) &&
// Check if resolvePath in pantheon API options is not null
pantheonAPIOptions.resolvePath != null
) {
Expand All @@ -95,6 +103,8 @@ export async function getServersideArticle({
return {
article,
grant,
publishingLevel,
versionId,
site,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
PantheonProvider,
PCCConvenienceFunctions,
updateConfig,
type PublishingLevel,
} from "@pantheon-systems/pcc-react-sdk";
import ArticleView from "../../../components/article-view";

Expand All @@ -17,9 +18,13 @@ updateConfig({
export const ClientsideArticleView = ({
article,
grant,
publishingLevel,
versionId,
}: {
article: Article;
grant?: string | undefined;
publishingLevel: keyof typeof PublishingLevel;
versionId: string | null;
}) => {
return (
<PantheonProvider
Expand All @@ -28,7 +33,11 @@ export const ClientsideArticleView = ({
pccGrant: grant,
})}
>
<ArticleView article={article} />
<ArticleView
article={article}
publishingLevel={publishingLevel}
versionId={versionId}
/>
</PantheonProvider>
);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
import {
getArticlePathComponentsFromContentStructure,
PCCConvenienceFunctions,
getArticlePathComponentsFromContentStructure
} from "@pantheon-systems/pcc-react-sdk/server";
} from "@pantheon-systems/pcc-react-sdk/server";
import { Metadata } from "next";
import { notFound } from "next/navigation";
import { StaticArticleView } from "../../../../components/article-view";
Expand All @@ -17,7 +17,6 @@ export const revalidate = 21600; // revalidate every 6 hours
export default async function ArticlePage({ params }: ArticlePageProps) {
const article = await PCCConvenienceFunctions.getArticleBySlugOrId(
params.uri[params.uri.length - 1],
"PRODUCTION",
);

if (!article) {
Expand All @@ -38,7 +37,6 @@ export async function generateMetadata({
}: ArticlePageProps): Promise<Metadata> {
const article = await PCCConvenienceFunctions.getArticleBySlugOrId(
params.uri[params.uri.length - 1],
"PRODUCTION",
);

return getSeoMetadata(article);
Expand All @@ -65,16 +63,16 @@ export async function generateStaticParams() {
site,
);

const id = article.id
const id = article.id;

// Add the ID to the article path
articlePath.push(id)
articlePath.push(id);

// Add a copy of the article path with the slug
const params = [{ uri: articlePath.slice() }];
if (article.metadata?.slug) {
// Change the ID in the article path to the slug
articlePath[articlePath.length - 1] = String(article.metadata.slug)
articlePath[articlePath.length - 1] = String(article.metadata.slug);

params.push({ uri: articlePath });
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { useArticle } from "@pantheon-systems/pcc-react-sdk";
import type { Article } from "@pantheon-systems/pcc-react-sdk";
import type { Article, PublishingLevel } from "@pantheon-systems/pcc-react-sdk";
import { ArticleRenderer } from "@pantheon-systems/pcc-react-sdk/components";
import Image from "next/image";
import Link from "next/link";
Expand Down Expand Up @@ -52,6 +52,8 @@ const componentOverrideMap = {
type ArticleViewProps = {
article: Article;
onlyContent?: boolean;
publishingLevel: keyof typeof PublishingLevel;
versionId: string | null;
};

const ArticleHeader = ({
Expand Down Expand Up @@ -105,7 +107,10 @@ const ArticleHeader = ({
);
};

export function StaticArticleView({ article, onlyContent }: ArticleViewProps) {
export function StaticArticleView({
article,
onlyContent,
}: Pick<ArticleViewProps, "article" | "onlyContent">) {
const seoMetadata = getSeoMetadata(article);

return (
Expand Down Expand Up @@ -144,15 +149,18 @@ export function StaticArticleView({ article, onlyContent }: ArticleViewProps) {
export default function ArticleView({
article,
onlyContent,
publishingLevel,
versionId,
}: ArticleViewProps) {
const { data } = useArticle(
article.id,
{
publishingLevel: article.publishingLevel,
publishingLevel,
versionId: versionId ?? undefined,
contentType: "TREE_PANTHEON_V2",
},
{
skip: article.publishingLevel !== "REALTIME",
skip: publishingLevel !== "REALTIME",
},
);

Expand Down
Loading