feat(SW-508): preview for content pages
This commit is contained in:
@@ -1,26 +1,29 @@
|
||||
import InitLivePreview from "@/components/Current/LivePreview"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
import "@/app/globals.css"
|
||||
import "@scandic-hotels/design-system/style.css"
|
||||
|
||||
import type { Metadata } from "next"
|
||||
import TrpcProvider from "@/lib/trpc/Provider"
|
||||
|
||||
import InitLivePreview from "@/components/LivePreview"
|
||||
import { getIntl } from "@/i18n"
|
||||
import ServerIntlProvider from "@/i18n/Provider"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import type { LangParams, LayoutArgs } from "@/types/params"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
description: "New web",
|
||||
title: "Scandic Hotels",
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
params,
|
||||
}: React.PropsWithChildren<LayoutArgs<LangParams>>) {
|
||||
setLang(params.lang)
|
||||
const { defaultLocale, locale, messages } = await getIntl()
|
||||
|
||||
return (
|
||||
<html lang={params.lang}>
|
||||
<body>
|
||||
<InitLivePreview />
|
||||
{children}
|
||||
<ServerIntlProvider intl={{ defaultLocale, locale, messages }}>
|
||||
<TrpcProvider>{children}</TrpcProvider>
|
||||
</ServerIntlProvider>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import ContentPage from "@/components/ContentType/ContentPage"
|
||||
import HotelPage from "@/components/ContentType/HotelPage"
|
||||
import LoyaltyPage from "@/components/ContentType/LoyaltyPage"
|
||||
import LoadingSpinner from "@/components/LoadingSpinner"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import {
|
||||
import type {
|
||||
ContentTypeParams,
|
||||
LangParams,
|
||||
PageArgs,
|
||||
@@ -13,12 +20,30 @@ export default async function PreviewPage({
|
||||
}: PageArgs<LangParams & ContentTypeParams & UIDParams, {}>) {
|
||||
setLang(params.lang)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>
|
||||
Preview for {params.contentType}:{params.uid} in {params.lang} with
|
||||
params <pre>{JSON.stringify(searchParams, null, 2)}</pre> goes here
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
try {
|
||||
ContentstackLivePreview.setConfigFromParams(searchParams)
|
||||
|
||||
if (!searchParams.live_preview) {
|
||||
return <LoadingSpinner />
|
||||
}
|
||||
|
||||
switch (params.contentType) {
|
||||
case "content-page":
|
||||
return <ContentPage />
|
||||
case "loyalty-page":
|
||||
return <LoyaltyPage />
|
||||
case "hotel-page":
|
||||
return <HotelPage />
|
||||
default:
|
||||
console.log({ PREVIEW: params })
|
||||
const type: never = params.contentType
|
||||
console.error(`Unsupported content type given: ${type}`)
|
||||
notFound()
|
||||
}
|
||||
} catch (error) {
|
||||
// TODO: throw 500
|
||||
console.error("Error in preview page")
|
||||
console.error(error)
|
||||
throw new Error("Something went wrong")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Footer from "@/components/Current/Footer"
|
||||
import LangPopup from "@/components/Current/LangPopup"
|
||||
import InitLivePreview from "@/components/Current/LivePreview"
|
||||
import InitLivePreview from "@/components/LivePreview"
|
||||
import SkipToMainContent from "@/components/SkipToMainContent"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ContentstackLivePreview from "@contentstack/live-preview-utils"
|
||||
import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
|
||||
|
||||
import { previewRequest } from "@/lib/graphql/previewRequest"
|
||||
import { GetCurrentBlockPage } from "@/lib/graphql/Query/Current/CurrentBlockPage.graphql"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import ContentstackLivePreview from "@contentstack/live-preview-utils"
|
||||
import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
|
||||
import { useEffect } from "react"
|
||||
|
||||
export default function InitLivePreview() {
|
||||
@@ -1,5 +1,6 @@
|
||||
import "server-only"
|
||||
|
||||
import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
|
||||
import { ClientError, GraphQLClient } from "graphql-request"
|
||||
|
||||
import { Lang } from "@/constants/languages"
|
||||
@@ -16,40 +17,54 @@ export async function request<T>(
|
||||
params?: RequestInit
|
||||
): Promise<Data<T>> {
|
||||
try {
|
||||
if (params?.cache) {
|
||||
client.requestConfig.cache = params.cache
|
||||
}
|
||||
if (params?.headers) {
|
||||
client.requestConfig.headers = params.headers
|
||||
}
|
||||
if (params?.next) {
|
||||
client.requestConfig.next = params.next
|
||||
}
|
||||
client.setHeaders({
|
||||
access_token: env.CMS_ACCESS_TOKEN,
|
||||
"Content-Type": "application/json",
|
||||
})
|
||||
|
||||
if (env.PRINT_QUERY) {
|
||||
const print = (await import("graphql/language/printer")).print
|
||||
const rawResponse = await client.rawRequest<T>(
|
||||
print(query as DocumentNode),
|
||||
variables,
|
||||
{
|
||||
access_token: env.CMS_ACCESS_TOKEN,
|
||||
"Content-Type": "application/json",
|
||||
const previewHash = ContentstackLivePreview.hash
|
||||
if (previewHash) {
|
||||
client.setEndpoint(env.CMS_PREVIEW_URL)
|
||||
client.setHeader("preview_token", env.CMS_PREVIEW_TOKEN)
|
||||
client.setHeader("live_preview", previewHash)
|
||||
} else {
|
||||
if (params?.cache) {
|
||||
client.requestConfig.cache = params.cache
|
||||
}
|
||||
if (params?.headers) {
|
||||
client.requestConfig.headers = params.headers
|
||||
}
|
||||
if (params?.next) {
|
||||
client.requestConfig.next = params.next
|
||||
}
|
||||
|
||||
if (env.PRINT_QUERY) {
|
||||
const print = (await import("graphql/language/printer")).print
|
||||
const rawResponse = await client.rawRequest<T>(
|
||||
print(query as DocumentNode),
|
||||
variables,
|
||||
{
|
||||
access_token: env.CMS_ACCESS_TOKEN,
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* TODO: Send to Monitoring (Logging and Metrics)
|
||||
*/
|
||||
console.log({
|
||||
complexityLimit: rawResponse.headers.get("x-query-complexity"),
|
||||
})
|
||||
console.log({
|
||||
referenceDepth: rawResponse.headers.get("x-reference-depth"),
|
||||
})
|
||||
console.log({
|
||||
resolverCost: rawResponse.headers.get("x-resolver-cost"),
|
||||
})
|
||||
|
||||
return {
|
||||
data: rawResponse.data,
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* TODO: Send to Monitoring (Logging and Metrics)
|
||||
*/
|
||||
console.log({
|
||||
complexityLimit: rawResponse.headers.get("x-query-complexity"),
|
||||
})
|
||||
console.log({
|
||||
referenceDepth: rawResponse.headers.get("x-reference-depth"),
|
||||
})
|
||||
console.log({ resolverCost: rawResponse.headers.get("x-resolver-cost") })
|
||||
|
||||
return {
|
||||
data: rawResponse.data,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,10 +93,6 @@ export async function request<T>(
|
||||
|
||||
const response = await client.request<T>({
|
||||
document: query,
|
||||
requestHeaders: {
|
||||
access_token: env.CMS_ACCESS_TOKEN,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
variables,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import "server-only"
|
||||
|
||||
import ContentstackLivePreview from "@contentstack/live-preview-utils"
|
||||
import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
|
||||
import { request as graphqlRequest } from "graphql-request"
|
||||
|
||||
import { env } from "@/env/server"
|
||||
|
||||
@@ -2,7 +2,6 @@ import { NextResponse } from "next/server"
|
||||
|
||||
import { notFound } from "@/server/errors/next"
|
||||
|
||||
import { resolve as resolveEntry } from "@/utils/entry"
|
||||
import { findLang } from "@/utils/languages"
|
||||
import { removeTrailingSlash } from "@/utils/url"
|
||||
|
||||
@@ -18,17 +17,21 @@ export const middleware: NextMiddleware = async (request) => {
|
||||
|
||||
const pathWithoutTrailingSlash = removeTrailingSlash(nextUrl.pathname)
|
||||
|
||||
const pathNameWithoutLang = pathWithoutTrailingSlash.replace(`/${lang}`, "")
|
||||
const contentTypePathName = pathWithoutTrailingSlash.replace(`/${lang}`, "")
|
||||
const isPreview = request.nextUrl.pathname.includes("/preview")
|
||||
|
||||
const searchParams = new URLSearchParams(request.nextUrl.searchParams)
|
||||
|
||||
const { contentType, uid } = await fetchAndCacheEntry(
|
||||
pathNameWithoutLang,
|
||||
isPreview
|
||||
? contentTypePathName.replace("/preview", "")
|
||||
: contentTypePathName,
|
||||
lang
|
||||
)
|
||||
|
||||
if (!contentType || !uid) {
|
||||
throw notFound(
|
||||
`Unable to resolve CMS entry for locale "${lang}": ${pathNameWithoutLang}`
|
||||
`Unable to resolve CMS entry for locale "${lang}": ${contentTypePathName}`
|
||||
)
|
||||
}
|
||||
const headers = getDefaultRequestHeaders(request)
|
||||
@@ -37,9 +40,9 @@ export const middleware: NextMiddleware = async (request) => {
|
||||
|
||||
const isCurrent = contentType ? contentType.indexOf("current") >= 0 : false
|
||||
|
||||
if (request.nextUrl.pathname.includes("/preview")) {
|
||||
if (isPreview) {
|
||||
if (isCurrent) {
|
||||
searchParams.set("uri", pathNameWithoutLang.replace("/preview", ""))
|
||||
searchParams.set("uri", contentTypePathName.replace("/preview", ""))
|
||||
return NextResponse.rewrite(
|
||||
new URL(`/${lang}/preview-current?${searchParams.toString()}`, nextUrl),
|
||||
{
|
||||
@@ -65,7 +68,7 @@ export const middleware: NextMiddleware = async (request) => {
|
||||
|
||||
if (isCurrent) {
|
||||
searchParams.set("uid", uid)
|
||||
searchParams.set("uri", pathNameWithoutLang)
|
||||
searchParams.set("uri", contentTypePathName)
|
||||
return NextResponse.rewrite(
|
||||
new URL(
|
||||
`/${lang}/current-content-page?${searchParams.toString()}`,
|
||||
|
||||
Reference in New Issue
Block a user