feat(ui): live preview conditions (#14012)
Supports live preview conditions. This is essentially access control for
live preview, where you may want to restrict who can use it based on
certain criteria, such as the current user or document data.
To do this, simply return null or undefined from your live preview url
functions:
```ts
url: ({ req }) => (req.user?.role === 'admin' ? '/hello-world' : null)
```
This is also useful for pages which derive their URL from document data,
e.g. a slug field, do not attempt to render the live preview window
until the URL is fully formatted.
For example, if you have a page in your front-end with the URL structure
of `/posts/[slug]`, the slug field is required before the page can
properly load. However, if the slug is not a required field, or when
drafts and/or autosave is enabled, the slug field might not yet have
data, leading to `/posts/undefined` or similar.
```ts
url: ({ data }) => data?.slug ? `/${data.slug}` : null
```
---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
- https://app.asana.com/0/0/1211513433305000
This commit is contained in:
19
test/live-preview/app/live-preview/(pages)/static/page.tsx
Normal file
19
test/live-preview/app/live-preview/(pages)/static/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Gutter } from '@payloadcms/ui'
|
||||
|
||||
import React, { Fragment } from 'react'
|
||||
|
||||
type Args = {
|
||||
params: Promise<{
|
||||
slug?: string
|
||||
}>
|
||||
}
|
||||
|
||||
export default async function TestPage(args: Args) {
|
||||
return (
|
||||
<Fragment>
|
||||
<Gutter>
|
||||
<p>This is a static page for testing.</p>
|
||||
</Gutter>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
20
test/live-preview/collections/NoURL.ts
Normal file
20
test/live-preview/collections/NoURL.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const NoURLCollection: CollectionConfig = {
|
||||
slug: 'no-url',
|
||||
admin: {
|
||||
livePreview: {
|
||||
url: ({ data }) => (data?.enabled ? '/live-preview/static' : null),
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'enabled',
|
||||
type: 'checkbox',
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { MediaBlock } from './blocks/MediaBlock/index.js'
|
||||
import { Categories } from './collections/Categories.js'
|
||||
import { CollectionLevelConfig } from './collections/CollectionLevelConfig.js'
|
||||
import { Media } from './collections/Media.js'
|
||||
import { NoURLCollection } from './collections/NoURL.js'
|
||||
import { Pages } from './collections/Pages.js'
|
||||
import { Posts } from './collections/Posts.js'
|
||||
import { SSR } from './collections/SSR.js'
|
||||
@@ -58,6 +59,7 @@ export default buildConfigWithDefaults({
|
||||
Media,
|
||||
CollectionLevelConfig,
|
||||
StaticURLCollection,
|
||||
NoURLCollection,
|
||||
],
|
||||
globals: [Header, Footer],
|
||||
onInit: seed,
|
||||
|
||||
@@ -9,7 +9,12 @@ import { fileURLToPath } from 'url'
|
||||
import type { PayloadTestSDK } from '../helpers/sdk/index.js'
|
||||
|
||||
import { devUser } from '../credentials.js'
|
||||
import { ensureCompilationIsDone, initPageConsoleErrorCatch, saveDocAndAssert } from '../helpers.js'
|
||||
import {
|
||||
ensureCompilationIsDone,
|
||||
initPageConsoleErrorCatch,
|
||||
saveDocAndAssert,
|
||||
// throttleTest,
|
||||
} from '../helpers.js'
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
|
||||
import {
|
||||
selectLivePreviewBreakpoint,
|
||||
@@ -55,6 +60,7 @@ describe('Live Preview', () => {
|
||||
let ssrAutosavePagesURLUtil: AdminUrlUtil
|
||||
let payload: PayloadTestSDK<Config>
|
||||
let user: any
|
||||
let context: any
|
||||
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
@@ -65,7 +71,7 @@ describe('Live Preview', () => {
|
||||
ssrPagesURLUtil = new AdminUrlUtil(serverURL, ssrPagesSlug)
|
||||
ssrAutosavePagesURLUtil = new AdminUrlUtil(serverURL, ssrAutosavePagesSlug)
|
||||
|
||||
const context = await browser.newContext()
|
||||
context = await browser.newContext()
|
||||
page = await context.newPage()
|
||||
|
||||
initPageConsoleErrorCatch(page)
|
||||
@@ -83,6 +89,12 @@ describe('Live Preview', () => {
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
// await throttleTest({
|
||||
// page,
|
||||
// context,
|
||||
// delay: 'Fast 4G',
|
||||
// })
|
||||
|
||||
await reInitializeDB({
|
||||
serverURL,
|
||||
snapshotKey: 'livePreviewTest',
|
||||
@@ -164,6 +176,24 @@ describe('Live Preview', () => {
|
||||
await expect.poll(async () => iframe.getAttribute('src')).toMatch(/\/live-preview/)
|
||||
})
|
||||
|
||||
test('collection — does not render iframe when live preview url is falsy', async () => {
|
||||
const noURL = new AdminUrlUtil(serverURL, 'no-url')
|
||||
await page.goto(noURL.create)
|
||||
await page.locator('#field-title').fill('No URL')
|
||||
await saveDocAndAssert(page)
|
||||
const toggler = page.locator('button#live-preview-toggler')
|
||||
await expect(toggler).toBeHidden()
|
||||
await expect(page.locator('iframe.live-preview-iframe')).toBeHidden()
|
||||
|
||||
const enabledCheckbox = page.locator('#field-enabled')
|
||||
await enabledCheckbox.check()
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
await expect(toggler).toBeVisible()
|
||||
await toggleLivePreview(page)
|
||||
await expect(page.locator('iframe.live-preview-iframe')).toBeVisible()
|
||||
})
|
||||
|
||||
test('collection — retains static URL across edits', async () => {
|
||||
const util = new AdminUrlUtil(serverURL, 'static-url')
|
||||
await page.goto(util.create)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Gutter } from '@payloadcms/ui'
|
||||
|
||||
import React, { Fragment } from 'react'
|
||||
|
||||
type Args = {
|
||||
params: Promise<{
|
||||
slug?: string
|
||||
}>
|
||||
}
|
||||
|
||||
export default async function TestPage(args: Args) {
|
||||
return (
|
||||
<Fragment>
|
||||
<Gutter>
|
||||
<p>This is a static page for testing.</p>
|
||||
</Gutter>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user