Merge branch '2.0' of github.com:payloadcms/payload into 2.0
This commit is contained in:
25
.github/workflows/main.yml
vendored
25
.github/workflows/main.yml
vendored
@@ -320,3 +320,28 @@ jobs:
|
||||
|
||||
- name: Build richtext-lexical
|
||||
run: pnpm turbo run build --filter=richtext-lexical
|
||||
|
||||
build-plugin-live-preview:
|
||||
runs-on: ubuntu-latest
|
||||
needs: core-build
|
||||
|
||||
steps:
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Restore build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- name: Build live-preview
|
||||
run: pnpm turbo run build --filter=live-preview
|
||||
|
||||
@@ -16,6 +16,11 @@ export async function migrate(this: PostgresAdapter): Promise<void> {
|
||||
const { payload } = this
|
||||
const migrationFiles = await readMigrationFiles({ payload })
|
||||
|
||||
if (!migrationFiles.length) {
|
||||
payload.logger.info({ msg: 'No migrations to run.' })
|
||||
return
|
||||
}
|
||||
|
||||
let latestBatch = 0
|
||||
let migrationsInDB = []
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview",
|
||||
"version": "1.0.0-beta.0",
|
||||
"version": "1.0.0-beta.1",
|
||||
"description": "The official live preview JavaScript SDK for Payload",
|
||||
"repository": "https://github.com/payloadcms/payload",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import { useWindowInfo } from '@faceless-ui/window-info'
|
||||
import { clearAllBodyScrollLocks, disableBodyScroll, enableBodyScroll } from 'body-scroll-lock'
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
|
||||
import { usePreferences } from '../../utilities/Preferences'
|
||||
import { disableBodyScroll, enableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock'
|
||||
|
||||
type NavContextType = {
|
||||
navOpen: boolean
|
||||
setNavOpen: (value: boolean) => void
|
||||
navRef: React.RefObject<HTMLDivElement>
|
||||
setNavOpen: (value: boolean) => void
|
||||
}
|
||||
|
||||
export const NavContext = React.createContext<NavContextType>({
|
||||
navOpen: false,
|
||||
setNavOpen: () => {},
|
||||
navOpen: true,
|
||||
navRef: null,
|
||||
setNavOpen: () => {},
|
||||
})
|
||||
|
||||
export const useNav = () => React.useContext(NavContext)
|
||||
@@ -42,7 +43,10 @@ export const NavProvider: React.FC<{
|
||||
const navPrefs = await getPreference('nav')
|
||||
const preferredState = navPrefs?.open
|
||||
if (typeof preferredState === 'boolean') {
|
||||
console.log({ navPrefs })
|
||||
setNavOpen(preferredState)
|
||||
} else {
|
||||
setNavOpen(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +98,6 @@ export const NavProvider: React.FC<{
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<NavContext.Provider value={{ navOpen, setNavOpen, navRef }}>{children}</NavContext.Provider>
|
||||
<NavContext.Provider value={{ navOpen, navRef, setNavOpen }}>{children}</NavContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { NavLink } from 'react-router-dom'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useConfig } from '../../utilities/Config'
|
||||
import { useAuth } from '../../utilities/Auth'
|
||||
import RenderCustomComponent from '../../utilities/RenderCustomComponent'
|
||||
import Chevron from '../../icons/Chevron'
|
||||
import Logout from '../Logout'
|
||||
import { EntityToGroup, EntityType, Group, groupNavItems } from '../../../utilities/groupNavItems'
|
||||
import { NavLink } from 'react-router-dom'
|
||||
|
||||
import type { EntityToGroup, Group } from '../../../utilities/groupNavItems'
|
||||
|
||||
import { getTranslation } from '../../../../utilities/getTranslation'
|
||||
import { EntityType, groupNavItems } from '../../../utilities/groupNavItems'
|
||||
import Chevron from '../../icons/Chevron'
|
||||
import { useAuth } from '../../utilities/Auth'
|
||||
import { useConfig } from '../../utilities/Config'
|
||||
import RenderCustomComponent from '../../utilities/RenderCustomComponent'
|
||||
import { Hamburger } from '../Hamburger'
|
||||
import Logout from '../Logout'
|
||||
import NavGroup from '../NavGroup'
|
||||
import { useNav } from './context'
|
||||
|
||||
import './index.scss'
|
||||
import { Hamburger } from '../Hamburger'
|
||||
|
||||
const baseClass = 'nav'
|
||||
|
||||
const DefaultNav: React.FC = () => {
|
||||
const { navOpen, setNavOpen, navRef } = useNav()
|
||||
const { navOpen, navRef, setNavOpen } = useNav()
|
||||
const { permissions, user } = useAuth()
|
||||
const [groups, setGroups] = useState<Group[]>([])
|
||||
const { t, i18n } = useTranslation('general')
|
||||
const { i18n } = useTranslation('general')
|
||||
|
||||
const {
|
||||
admin: {
|
||||
components: { afterNavLinks, beforeNavLinks },
|
||||
},
|
||||
collections,
|
||||
globals,
|
||||
routes: { admin },
|
||||
admin: {
|
||||
components: { beforeNavLinks, afterNavLinks },
|
||||
},
|
||||
} = useConfig()
|
||||
|
||||
useEffect(() => {
|
||||
@@ -42,8 +44,8 @@ const DefaultNav: React.FC = () => {
|
||||
)
|
||||
.map((collection) => {
|
||||
const entityToGroup: EntityToGroup = {
|
||||
type: EntityType.collection,
|
||||
entity: collection,
|
||||
type: EntityType.collection,
|
||||
}
|
||||
|
||||
return entityToGroup
|
||||
@@ -55,8 +57,8 @@ const DefaultNav: React.FC = () => {
|
||||
)
|
||||
.map((global) => {
|
||||
const entityToGroup: EntityToGroup = {
|
||||
type: EntityType.global,
|
||||
entity: global,
|
||||
type: EntityType.global,
|
||||
}
|
||||
|
||||
return entityToGroup
|
||||
@@ -74,7 +76,7 @@ const DefaultNav: React.FC = () => {
|
||||
<nav className={`${baseClass}__wrap`}>
|
||||
{Array.isArray(beforeNavLinks) &&
|
||||
beforeNavLinks.map((Component, i) => <Component key={i} />)}
|
||||
{groups.map(({ label, entities }, key) => {
|
||||
{groups.map(({ entities, label }, key) => {
|
||||
return (
|
||||
<NavGroup {...{ key, label }}>
|
||||
{entities.map(({ entity, type }, i) => {
|
||||
@@ -96,9 +98,9 @@ const DefaultNav: React.FC = () => {
|
||||
|
||||
return (
|
||||
<NavLink
|
||||
id={id}
|
||||
className={`${baseClass}__link`}
|
||||
activeClassName="active"
|
||||
className={`${baseClass}__link`}
|
||||
id={id}
|
||||
key={i}
|
||||
to={href}
|
||||
>
|
||||
@@ -126,6 +128,7 @@ const DefaultNav: React.FC = () => {
|
||||
onClick={() => {
|
||||
setNavOpen(false)
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<Hamburger isActive />
|
||||
</button>
|
||||
|
||||
@@ -3,16 +3,15 @@ import { useTranslation } from 'react-i18next'
|
||||
|
||||
import type { Props } from './types'
|
||||
|
||||
import { Hamburger } from '../../elements/Hamburger'
|
||||
import { AppHeader } from '../../elements/Header'
|
||||
import { Nav as DefaultNav } from '../../elements/Nav'
|
||||
import { NavToggler } from '../../elements/Nav/NavToggler'
|
||||
import { useNav } from '../../elements/Nav/context'
|
||||
import { useConfig } from '../../utilities/Config'
|
||||
import Meta from '../../utilities/Meta'
|
||||
import RenderCustomComponent from '../../utilities/RenderCustomComponent'
|
||||
import { Nav as DefaultNav } from '../../elements/Nav'
|
||||
import { useNav } from '../../elements/Nav/context'
|
||||
import { NavToggler } from '../../elements/Nav/NavToggler'
|
||||
|
||||
import './index.scss'
|
||||
import { Hamburger } from '../../elements/Hamburger'
|
||||
|
||||
const baseClass = 'template-default'
|
||||
|
||||
@@ -46,15 +45,15 @@ const Default: React.FC<Props> = ({ children, className }) => {
|
||||
<AppHeader />
|
||||
{children}
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t('close')}
|
||||
className={`${baseClass}__nav-overlay`}
|
||||
aria-label={t('menu')}
|
||||
onClick={() => setNavOpen(!navOpen)}
|
||||
type="button"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<NavToggler className={`${baseClass}__nav-toggler`} id="nav-toggler">
|
||||
<Hamburger isActive={navOpen} closeIcon="collapse" />
|
||||
<Hamburger closeIcon="collapse" isActive={navOpen} />
|
||||
</NavToggler>
|
||||
</Fragment>
|
||||
)
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
padding-left: calc(var(--base) * 2);
|
||||
}
|
||||
}
|
||||
|
||||
&__fields {
|
||||
& > .tabs-field {
|
||||
margin-right: calc(var(--base) * -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +107,12 @@
|
||||
padding-left: var(--gutter-h);
|
||||
}
|
||||
}
|
||||
|
||||
&__fields {
|
||||
& > .tabs-field {
|
||||
margin-right: calc(var(--gutter-h) * -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
padding-left: calc(var(--base) * 2);
|
||||
}
|
||||
}
|
||||
|
||||
&__fields {
|
||||
& > .tabs-field {
|
||||
margin-right: calc(var(--base) * -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +103,12 @@
|
||||
padding-left: var(--gutter-h);
|
||||
}
|
||||
}
|
||||
|
||||
&__fields {
|
||||
& > .tabs-field {
|
||||
margin-right: calc(var(--gutter-h) * -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import CustomDefaultView from './components/views/CustomDefault'
|
||||
import CustomEditView from './components/views/CustomEdit'
|
||||
import CustomVersionsView from './components/views/CustomVersions'
|
||||
import CustomView from './components/views/CustomView'
|
||||
import { globalSlug, slug, slugPluralLabel, slugSingularLabel } from './shared'
|
||||
import { globalSlug, postsSlug, slugPluralLabel, slugSingularLabel } from './shared'
|
||||
|
||||
export interface Post {
|
||||
createdAt: Date
|
||||
@@ -89,7 +89,7 @@ export default buildConfigWithDefaults({
|
||||
],
|
||||
},
|
||||
{
|
||||
slug,
|
||||
slug: postsSlug,
|
||||
labels: {
|
||||
singular: slugSingularLabel,
|
||||
plural: slugPluralLabel,
|
||||
@@ -105,6 +105,12 @@ export default buildConfigWithDefaults({
|
||||
versions: {
|
||||
drafts: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
{
|
||||
label: 'Tab 1',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
@@ -138,6 +144,10 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'sidebarField',
|
||||
type: 'text',
|
||||
@@ -380,7 +390,7 @@ export default buildConfigWithDefaults({
|
||||
|
||||
await mapAsync([...Array(11)], async () => {
|
||||
await payload.create({
|
||||
collection: slug,
|
||||
collection: postsSlug,
|
||||
data: {
|
||||
title: 'title',
|
||||
description: 'description',
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
} from '../helpers'
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil'
|
||||
import { initPayloadE2E } from '../helpers/configHelpers'
|
||||
import { globalSlug, slug, slugPluralLabel } from './shared'
|
||||
import { globalSlug, postsSlug, slugPluralLabel } from './shared'
|
||||
|
||||
const { afterEach, beforeAll, beforeEach, describe } = test
|
||||
|
||||
@@ -33,7 +33,7 @@ describe('admin', () => {
|
||||
beforeAll(async ({ browser }) => {
|
||||
serverURL = (await initPayloadE2E(__dirname)).serverURL
|
||||
await clearDocs() // Clear any seeded data from onInit
|
||||
url = new AdminUrlUtil(serverURL, slug)
|
||||
url = new AdminUrlUtil(serverURL, postsSlug)
|
||||
|
||||
const context = await browser.newContext()
|
||||
page = await context.newPage()
|
||||
@@ -52,7 +52,7 @@ describe('admin', () => {
|
||||
test('should nav to collection - nav', async () => {
|
||||
await page.goto(url.admin)
|
||||
await openNav(page)
|
||||
await page.locator(`#nav-${slug}`).click()
|
||||
await page.locator(`#nav-${postsSlug}`).click()
|
||||
expect(page.url()).toContain(url.list)
|
||||
})
|
||||
|
||||
@@ -66,7 +66,7 @@ describe('admin', () => {
|
||||
test('should navigate to collection - card', async () => {
|
||||
await page.goto(url.admin)
|
||||
await wait(200)
|
||||
await page.locator(`#card-${slug}`).click()
|
||||
await page.locator(`#card-${postsSlug}`).click()
|
||||
expect(page.url()).toContain(url.list)
|
||||
})
|
||||
|
||||
@@ -122,7 +122,9 @@ describe('admin', () => {
|
||||
test('breadcrumbs - from document to collection', async () => {
|
||||
const { id } = await createPost()
|
||||
await page.goto(url.edit(id))
|
||||
const collectionBreadcrumb = page.locator(`.step-nav a[href="/admin/collections/${slug}"]`)
|
||||
const collectionBreadcrumb = page.locator(
|
||||
`.step-nav a[href="/admin/collections/${postsSlug}"]`,
|
||||
)
|
||||
await expect(collectionBreadcrumb).toBeVisible()
|
||||
await expect(collectionBreadcrumb).toHaveText(slugPluralLabel)
|
||||
expect(page.url()).toContain(url.list)
|
||||
@@ -866,7 +868,7 @@ describe('admin', () => {
|
||||
|
||||
async function createPost(overrides?: Partial<Post>): Promise<Post> {
|
||||
return payload.create({
|
||||
collection: slug,
|
||||
collection: postsSlug,
|
||||
data: {
|
||||
title,
|
||||
description,
|
||||
@@ -876,9 +878,9 @@ async function createPost(overrides?: Partial<Post>): Promise<Post> {
|
||||
}
|
||||
|
||||
async function clearDocs(): Promise<void> {
|
||||
const allDocs = await payload.find({ collection: slug, limit: 100 })
|
||||
const allDocs = await payload.find({ collection: postsSlug, limit: 100 })
|
||||
const ids = allDocs.docs.map((doc) => doc.id)
|
||||
await mapAsync(ids, async (id) => {
|
||||
await payload.delete({ collection: slug, id })
|
||||
await payload.delete({ collection: postsSlug, id })
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const slug = 'posts'
|
||||
export const postsSlug = 'posts'
|
||||
|
||||
export const slugSingularLabel = 'Post'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user