From 3032e0b5a239db0762abd120b2db95f30ed5ca65 Mon Sep 17 00:00:00 2001 From: Jacob Fletcher Date: Tue, 24 Oct 2023 23:32:55 -0400 Subject: [PATCH] fix: global permissions for live preview (#3854) --- .../elements/DocumentFields/index.scss | 29 +++++++++ .../elements/DocumentFields/index.tsx | 9 ++- .../components/views/LivePreview/index.scss | 24 ------- .../components/views/LivePreview/index.tsx | 34 ++++------ test/live-preview/e2e.spec.ts | 65 ++++++++++++------- test/live-preview/globals/Footer.ts | 1 + test/live-preview/globals/Header.ts | 1 + 7 files changed, 91 insertions(+), 72 deletions(-) diff --git a/packages/payload/src/admin/components/elements/DocumentFields/index.scss b/packages/payload/src/admin/components/elements/DocumentFields/index.scss index 152f6e52f3..e6b614c635 100644 --- a/packages/payload/src/admin/components/elements/DocumentFields/index.scss +++ b/packages/payload/src/admin/components/elements/DocumentFields/index.scss @@ -82,6 +82,35 @@ color: var(--theme-elevation-400); } + &--force-sidebar-wrap { + display: block; + + .document-fields { + &__main { + width: 100%; + min-height: initial; + } + + &__sidebar-wrap { + position: static; + width: 100%; + height: initial; + border-left: 0; + } + + &__sidebar { + padding-bottom: base(3.5); + overflow: visible; + } + + &__sidebar-fields { + padding-top: 0; + padding-left: var(--gutter-h); + padding-bottom: 0; + } + } + } + @include mid-break { display: block; diff --git a/packages/payload/src/admin/components/elements/DocumentFields/index.tsx b/packages/payload/src/admin/components/elements/DocumentFields/index.tsx index 81517a4249..7fd8878f9d 100644 --- a/packages/payload/src/admin/components/elements/DocumentFields/index.tsx +++ b/packages/payload/src/admin/components/elements/DocumentFields/index.tsx @@ -19,6 +19,7 @@ export const DocumentFields: React.FC<{ description?: Description fieldTypes: FieldTypes fields: FieldWithPath[] + forceSidebarWrap?: boolean hasSavePermission: boolean permissions: CollectionPermission | GlobalPermission }> = (props) => { @@ -28,6 +29,7 @@ export const DocumentFields: React.FC<{ description, fieldTypes, fields, + forceSidebarWrap, hasSavePermission, permissions, } = props @@ -40,14 +42,15 @@ export const DocumentFields: React.FC<{ readOnly: !hasSavePermission, }) - const hasSidebar = sidebarFields && sidebarFields.length > 0 + const hasSidebarFields = sidebarFields && sidebarFields.length > 0 return (
- {hasSidebar && ( + {hasSidebarFields && (
diff --git a/packages/payload/src/admin/components/views/LivePreview/index.scss b/packages/payload/src/admin/components/views/LivePreview/index.scss index 9a0c8cc1f0..4d5e743c41 100644 --- a/packages/payload/src/admin/components/views/LivePreview/index.scss +++ b/packages/payload/src/admin/components/views/LivePreview/index.scss @@ -41,18 +41,6 @@ } } - &__edit { - padding-top: calc(var(--base) * 1.5); - padding-bottom: base(4); - flex-grow: 1; - padding-right: calc(var(--base) * 2); - - [dir='rtl'] & { - padding-right: 0; - padding-left: calc(var(--base) * 2); - } - } - @include mid-break { flex-direction: column; @@ -68,18 +56,6 @@ &__form { display: block; } - - &__edit { - padding-top: var(--base); - padding-bottom: 0; - padding-right: var(--gutter-h); - } - } - - @include small-break { - &__edit { - padding-top: calc(var(--base) / 2); - } } } diff --git a/packages/payload/src/admin/components/views/LivePreview/index.tsx b/packages/payload/src/admin/components/views/LivePreview/index.tsx index 6c50446bd6..b83aafbf64 100644 --- a/packages/payload/src/admin/components/views/LivePreview/index.tsx +++ b/packages/payload/src/admin/components/views/LivePreview/index.tsx @@ -10,9 +10,8 @@ import type { EditViewProps } from '../types' import { getTranslation } from '../../../../utilities/getTranslation' import { DocumentControls } from '../../elements/DocumentControls' +import { DocumentFields } from '../../elements/DocumentFields' import { Gutter } from '../../elements/Gutter' -import RenderFields from '../../forms/RenderFields' -import { filterFields } from '../../forms/RenderFields/filterFields' import { LeaveWithoutSaving } from '../../modals/LeaveWithoutSaving' import { useConfig } from '../../utilities/Config' import { useDocumentInfo } from '../../utilities/DocumentInfo' @@ -46,6 +45,7 @@ const PreviewView: React.FC< let id: string let fields: Field[] = [] let label: SanitizedGlobalConfig['label'] + let description: SanitizedGlobalConfig['admin']['description'] if ('collection' in props) { collection = props?.collection @@ -61,16 +61,10 @@ const PreviewView: React.FC< global = props?.global fields = props?.global?.fields label = props?.global?.label + description = props?.global?.admin?.description + hasSavePermission = permissions?.update?.permission } - const sidebarFields = filterFields({ - fieldSchema: fields, - fieldTypes, - filter: (field) => field?.admin?.position === 'sidebar', - permissions: permissions.fields, - readOnly: !hasSavePermission, - }) - return ( {collection && ( @@ -124,18 +118,14 @@ const PreviewView: React.FC< .filter(Boolean) .join(' ')} > - - !field?.admin?.position || field?.admin?.position !== 'sidebar'} - permissions={permissions.fields} - readOnly={!hasSavePermission} - /> - {sidebarFields && sidebarFields.length > 0 && ( - - )} - +
diff --git a/test/live-preview/e2e.spec.ts b/test/live-preview/e2e.spec.ts index 2d49e8e3fb..7f1cfe3386 100644 --- a/test/live-preview/e2e.spec.ts +++ b/test/live-preview/e2e.spec.ts @@ -19,6 +19,17 @@ const goToDoc = async (page: Page) => { await linkToDoc.click() } +const goToCollectionPreview = async (page: Page): Promise => { + await goToDoc(page) + await page.goto(`${page.url()}/preview`) +} + +const goToGlobalPreview = async (page: Page, slug: string): Promise => { + const global = new AdminUrlUtil(serverURL, slug) + const previewURL = `${global.global(slug)}/preview` + await page.goto(previewURL) +} + describe('Live Preview', () => { let page: Page @@ -49,24 +60,29 @@ describe('Live Preview', () => { }) test('collection - has route', async () => { - await goToDoc(page) - const docURL = page.url() - await page.goto(`${docURL}/preview`) - expect(page.url()).toBe(`${docURL}/preview`) + const url = page.url() + await goToCollectionPreview(page) + expect(page.url()).toBe(`${url}/preview`) }) test('collection - renders iframe', async () => { - await goToDoc(page) - const docURL = page.url() - await page.goto(`${docURL}/preview`) - expect(page.url()).toBe(`${docURL}/preview`) + await goToCollectionPreview(page) const iframe = page.locator('iframe.live-preview-iframe') await expect(iframe).toBeVisible() }) + test('collection - can edit fields', async () => { + await goToCollectionPreview(page) + const field = page.locator('#field-title') + await expect(field).toBeVisible() + await field.fill('Title 1') + await saveDocAndAssert(page) + }) + test('global - has tab', async () => { const global = new AdminUrlUtil(serverURL, 'header') await page.goto(global.global('header')) + const docURL = page.url() const pathname = new URL(docURL).pathname @@ -80,31 +96,35 @@ describe('Live Preview', () => { }) test('global - has route', async () => { - const global = new AdminUrlUtil(serverURL, 'header') - const previewURL = `${global.global('header')}/preview` - await page.goto(previewURL) - expect(page.url()).toBe(previewURL) + const url = page.url() + await goToGlobalPreview(page, 'header') + expect(page.url()).toBe(`${url}/preview`) }) test('global - renders iframe', async () => { - const global = new AdminUrlUtil(serverURL, 'header') - await page.goto(global.global('header')) - const docURL = page.url() - await page.goto(`${docURL}/preview`) - expect(page.url()).toBe(`${docURL}/preview`) + await goToGlobalPreview(page, 'header') const iframe = page.locator('iframe.live-preview-iframe') await expect(iframe).toBeVisible() }) + test('global - can edit fields', async () => { + await goToGlobalPreview(page, 'header') + const field = page.locator('input#field-navItems__0__link__newTab') + await expect(field).toBeVisible() + await expect(field).toBeEnabled() + await field.check() + await saveDocAndAssert(page) + }) + test('properly measures iframe and displays size', async () => { await page.goto(url.create) await page.locator('#field-title').fill('Title 3') await page.locator('#field-slug').fill('slug-3') await saveDocAndAssert(page) - const docURL = page.url() - await page.goto(`${docURL}/preview`) - expect(page.url()).toBe(`${docURL}/preview`) + await goToCollectionPreview(page) + expect(page.url()).toContain('/preview') + const iframe = page.locator('iframe') // Measure the actual iframe size and compare it with the inputs rendered in the toolbar @@ -137,9 +157,8 @@ describe('Live Preview', () => { await page.locator('#field-slug').fill('slug-4') await saveDocAndAssert(page) - const docURL = page.url() - await page.goto(`${docURL}/preview`) - expect(page.url()).toBe(`${docURL}/preview`) + await goToCollectionPreview(page) + expect(page.url()).toContain('/preview') const breakpointSelector = page.locator( '.live-preview-toolbar select[name="live-preview-breakpoint"]', diff --git a/test/live-preview/globals/Footer.ts b/test/live-preview/globals/Footer.ts index a8fcaf6ae9..148856484e 100644 --- a/test/live-preview/globals/Footer.ts +++ b/test/live-preview/globals/Footer.ts @@ -6,6 +6,7 @@ export const Footer: GlobalConfig = { slug: 'footer', access: { read: () => true, + update: () => true, }, fields: [ { diff --git a/test/live-preview/globals/Header.ts b/test/live-preview/globals/Header.ts index 74c7fb53fc..b9b00a624e 100644 --- a/test/live-preview/globals/Header.ts +++ b/test/live-preview/globals/Header.ts @@ -6,6 +6,7 @@ export const Header: GlobalConfig = { slug: 'header', access: { read: () => true, + update: () => true, }, fields: [ {