Mounts live preview to `../:id` instead `../:id/preview`. This is a huge win for both UX and a maintainability standpoint. Here are just a few of those wins: 1. If you edit a document, _then_ decide you want to preview those changes, you are currently presented with the `LeaveWithoutSaving` modal and are forced to either save your edits or clear them. This is because you are being navigated to an entirely new page with it's own form context. Instead, you should be able to freely navigate back and forth between the two. 2. If you are an editor who most often uses Live Preview, or you are editing a collection that typically requires it, you likely want it to automatically enter live preview mode when you open a document. Currently, the user has to navigate to the document _first_, then use the live preview tab. Instead, you should be able to set a preference and avoid this extra step. 3. Since the inception of Live Preview, we've been maintaining largely the same code across the default edit view and the live preview view, which often became out of sync and inconsistent—but they're essentially doing the same thing. While we could abstract a lot of this out, it is no longer necessary if the two views are combined into one. This change does also include some small modifications to UI. The "Live Preview" tab no longer exists, and instead has been replaced with a button placed next to the document controls (subject to change). Before: https://github.com/user-attachments/assets/48518b02-87ba-4750-ba7b-b21b5c75240a After: https://github.com/user-attachments/assets/a8ec8657-a6d6-4ee1-b9a7-3c1173bcfa96
46 lines
1.3 KiB
TypeScript
46 lines
1.3 KiB
TypeScript
import type { LivePreviewConfig } from 'payload'
|
|
|
|
export const formatLivePreviewURL: LivePreviewConfig['url'] = async ({
|
|
data,
|
|
collectionConfig,
|
|
req,
|
|
}) => {
|
|
let baseURL = `/live-preview`
|
|
|
|
// You can run async requests here, if needed
|
|
// For example, multi-tenant apps may need to lookup additional data
|
|
if (data?.tenant) {
|
|
try {
|
|
const fullTenant = await req.payload
|
|
.find({
|
|
collection: 'tenants',
|
|
where: {
|
|
id: {
|
|
equals: data.tenant,
|
|
},
|
|
},
|
|
limit: 1,
|
|
depth: 0,
|
|
})
|
|
.then((res) => res?.docs?.[0])
|
|
|
|
if (fullTenant?.clientURL) {
|
|
// Note: appending a fully-qualified URL here won't work for preview deployments on Vercel
|
|
baseURL = `${fullTenant.clientURL}/live-preview`
|
|
}
|
|
} catch (e) {
|
|
console.error(e)
|
|
}
|
|
}
|
|
|
|
// Format the URL as needed, based on the document and data
|
|
// I.e. append '/posts' to the URL if the document is a post
|
|
// You can also do this on individual collection or global config, if preferred
|
|
const isPage = collectionConfig && collectionConfig.slug === 'pages'
|
|
const isHomePage = isPage && data?.slug === 'home'
|
|
|
|
return `${baseURL}${
|
|
!isPage && collectionConfig ? `/${collectionConfig.slug}` : ''
|
|
}${!isHomePage && data?.slug ? `/${data.slug}` : ''}`
|
|
}
|