Compare commits
14 Commits
v3.0.0-bet
...
v3.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d6e7f8a37 | ||
|
|
3d37d74c6e | ||
|
|
de19822ed4 | ||
|
|
2b2bcb5264 | ||
|
|
e9b01e6d9f | ||
|
|
b0a760193e | ||
|
|
95569e44e4 | ||
|
|
11816080a6 | ||
|
|
3a86822f0a | ||
|
|
6f8604e18c | ||
|
|
aec3f5e308 | ||
|
|
e0a5de6730 | ||
|
|
5eee49da9a | ||
|
|
b7d01dec70 |
2
.github/actions/setup/action.yml
vendored
2
.github/actions/setup/action.yml
vendored
@@ -25,7 +25,7 @@ runs:
|
||||
node-version: ${{ inputs.node-version }}
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: ${{ inputs.pnpm-version }}
|
||||
run_install: false
|
||||
|
||||
@@ -119,7 +119,7 @@ A function that allows you to return any meta title, including from document's c
|
||||
{
|
||||
// ...
|
||||
seoPlugin({
|
||||
generateTitle: ({ ...docInfo, doc, locale }) => `Website.com — ${doc?.title}`,
|
||||
generateTitle: ({ ...docInfo, doc, locale, req }) => `Website.com — ${doc?.title}`,
|
||||
})
|
||||
}
|
||||
```
|
||||
@@ -133,7 +133,7 @@ A function that allows you to return any meta description, including from docume
|
||||
{
|
||||
// ...
|
||||
seoPlugin({
|
||||
generateDescription: ({ ...docInfo, doc, locale }) => doc?.excerpt,
|
||||
generateDescription: ({ ...docInfo, doc, locale, req }) => doc?.excerpt,
|
||||
})
|
||||
}
|
||||
```
|
||||
@@ -147,7 +147,7 @@ A function that allows you to return any meta image, including from document's c
|
||||
{
|
||||
// ...
|
||||
seoPlugin({
|
||||
generateImage: ({ ...docInfo, doc, locale }) => doc?.featuredImage,
|
||||
generateImage: ({ ...docInfo, doc, locale, req }) => doc?.featuredImage,
|
||||
})
|
||||
}
|
||||
```
|
||||
@@ -161,7 +161,7 @@ A function called by the search preview component to display the actual URL of y
|
||||
{
|
||||
// ...
|
||||
seoPlugin({
|
||||
generateURL: ({ ...docInfo, doc, locale }) =>
|
||||
generateURL: ({ ...docInfo, doc, locale, req }) =>
|
||||
`https://yoursite.com/${collection?.slug}/${doc?.slug}`,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload-monorepo",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-payload-app",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-mongodb",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The officially supported MongoDB database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-postgres",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The officially supported Postgres database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-sqlite",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The officially supported SQLite database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/drizzle",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "A library of shared functions used by different payload database adapters",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
@@ -58,11 +58,13 @@
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
},
|
||||
"./types": {
|
||||
"import": "./dist/types.js",
|
||||
"types": "./dist/types.d.ts"
|
||||
"types": "./dist/types.d.ts",
|
||||
"default": "./dist/types.js"
|
||||
}
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-nodemailer",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Payload Nodemailer Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-resend",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Payload Resend Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/graphql",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview-react",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The official React SDK for Payload Live Preview",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview-vue",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The official Vue SDK for Payload Live Preview",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The official live preview JavaScript SDK for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/next",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
.doc-header {
|
||||
width: 100%;
|
||||
margin-top: base(0.5);
|
||||
padding-bottom: calc(var(--base) * 1.5);
|
||||
margin-top: base(0.4);
|
||||
padding-bottom: calc(var(--base) * 1.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
@@ -27,6 +27,9 @@
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin: 0;
|
||||
padding-bottom: base(0.2);
|
||||
line-height: 1;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
position: absolute;
|
||||
order: 3;
|
||||
left: unset;
|
||||
inset-inline-end: base(0.5);
|
||||
inset-inline-end: base(0.8);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: var(--theme-elevation-600);
|
||||
@@ -16,8 +16,8 @@
|
||||
border: none;
|
||||
|
||||
svg {
|
||||
width: base(0.75);
|
||||
height: base(0.75);
|
||||
width: base(0.8);
|
||||
height: base(0.8);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@@ -33,10 +33,11 @@
|
||||
|
||||
.toast-title {
|
||||
line-height: base(1);
|
||||
margin-right: base(1);
|
||||
}
|
||||
|
||||
.payload-toast-item {
|
||||
padding: base(0.5);
|
||||
padding: base(0.8);
|
||||
color: var(--theme-elevation-800);
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
@@ -69,8 +70,8 @@
|
||||
}
|
||||
|
||||
.toast-icon {
|
||||
width: base(1);
|
||||
height: base(1);
|
||||
width: base(0.8);
|
||||
height: base(0.8);
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -84,8 +85,8 @@
|
||||
|
||||
&.toast-warning {
|
||||
color: var(--theme-warning-800);
|
||||
border-color: var(--theme-warning-150);
|
||||
background-color: var(--theme-warning-50);
|
||||
border-color: var(--theme-warning-250);
|
||||
background-color: var(--theme-warning-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-warning-600);
|
||||
@@ -98,8 +99,8 @@
|
||||
|
||||
&.toast-error {
|
||||
color: var(--theme-error-800);
|
||||
border-color: var(--theme-error-150);
|
||||
background-color: var(--theme-error-50);
|
||||
border-color: var(--theme-error-250);
|
||||
background-color: var(--theme-error-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-error-600);
|
||||
@@ -112,8 +113,8 @@
|
||||
|
||||
&.toast-success {
|
||||
color: var(--theme-success-800);
|
||||
border-color: var(--theme-success-150);
|
||||
background-color: var(--theme-success-50);
|
||||
border-color: var(--theme-success-250);
|
||||
background-color: var(--theme-success-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-success-600);
|
||||
@@ -126,8 +127,8 @@
|
||||
|
||||
&.toast-info {
|
||||
color: var(--theme-elevation-800);
|
||||
border-color: var(--theme-elevation-150);
|
||||
background-color: var(--theme-elevation-50);
|
||||
border-color: var(--theme-elevation-250);
|
||||
background-color: var(--theme-elevation-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-elevation-600);
|
||||
|
||||
@@ -149,8 +149,10 @@ export const Auth: React.FC<Props> = (props) => {
|
||||
{(showPasswordFields || requirePassword) && (
|
||||
<div className={`${baseClass}__changing-password`}>
|
||||
<PasswordField
|
||||
autoComplete="new-password"
|
||||
field={{
|
||||
name: 'password',
|
||||
_path: 'password',
|
||||
admin: {
|
||||
disabled,
|
||||
},
|
||||
|
||||
@@ -98,14 +98,18 @@ export const DefaultEditView: React.FC = () => {
|
||||
if (globalSlug) classes.push(`global-edit--${globalSlug}`)
|
||||
if (collectionSlug) classes.push(`collection-edit--${collectionSlug}`)
|
||||
|
||||
const [schemaPath, setSchemaPath] = React.useState(entitySlug)
|
||||
const [schemaPath, setSchemaPath] = React.useState(() => {
|
||||
if (operation === 'create' && auth && !auth.disableLocalStrategy) {
|
||||
return `_${entitySlug}.auth`
|
||||
}
|
||||
|
||||
return entitySlug
|
||||
})
|
||||
const [validateBeforeSubmit, setValidateBeforeSubmit] = useState(() => {
|
||||
if (
|
||||
operation === 'create' &&
|
||||
collectionConfig.auth &&
|
||||
!collectionConfig.auth.disableLocalStrategy
|
||||
)
|
||||
if (operation === 'create' && auth && !auth.disableLocalStrategy) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: flex-end;
|
||||
flex-wrap: wrap;
|
||||
gap: base(0.8);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
.pill {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
margin: 0 0 base(0.2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env node --no-deprecation
|
||||
#!/usr/bin/env -S node --no-deprecation
|
||||
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath, pathToFileURL } from 'node:url'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Node, React, Headless CMS and Application Framework built on Next.js",
|
||||
"keywords": [
|
||||
"admin panel",
|
||||
|
||||
@@ -44,11 +44,11 @@ export const ensureUsernameOrEmail = <TSlug extends CollectionSlug>({
|
||||
missingFields = true
|
||||
}
|
||||
// prevent clearing email if no username
|
||||
if ('email' in data && !data.email && !originalDoc.username) {
|
||||
if ('email' in data && !data.email && !originalDoc.username && !data?.username) {
|
||||
missingFields = true
|
||||
}
|
||||
// prevent clearing username if no email
|
||||
if ('username' in data && !data.username && !originalDoc.email) {
|
||||
if ('username' in data && !data.username && !originalDoc.email && !data?.email) {
|
||||
missingFields = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,7 +962,9 @@ export type SingleRelationshipFieldClient = {
|
||||
|
||||
export type RelationshipField = PolymorphicRelationshipField | SingleRelationshipField
|
||||
|
||||
export type RelationshipFieldClient = PolymorphicRelationshipFieldClient
|
||||
export type RelationshipFieldClient =
|
||||
| PolymorphicRelationshipFieldClient
|
||||
| SingleRelationshipFieldClient
|
||||
|
||||
export type ValueWithRelation = {
|
||||
relationTo: CollectionSlug
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-cloud-storage",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The official cloud storage plugin for Payload CMS",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-cloud",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The official Payload Cloud plugin",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-form-builder",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Form builder plugin for Payload CMS",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-nested-docs",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The official Nested Docs plugin for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-redirects",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Redirects plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-relationship-object-ids",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "A Payload plugin to store all relationship IDs as ObjectIDs",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-search",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Search plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-seo",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "SEO plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -61,7 +61,7 @@ export const MetaDescriptionComponent: React.FC<MetaDescriptionProps> = (props)
|
||||
...docInfo,
|
||||
doc: { ...getData() },
|
||||
locale: typeof locale === 'object' ? locale?.code : locale,
|
||||
} satisfies Parameters<GenerateDescription>[0]),
|
||||
} satisfies Omit<Parameters<GenerateDescription>[0], 'req'>),
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -57,7 +57,7 @@ export const MetaImageComponent: React.FC<MetaImageProps> = (props) => {
|
||||
...docInfo,
|
||||
doc: { ...getData() },
|
||||
locale: typeof locale === 'object' ? locale?.code : locale,
|
||||
} satisfies Parameters<GenerateImage>[0]),
|
||||
} satisfies Omit<Parameters<GenerateImage>[0], 'req'>),
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -62,7 +62,7 @@ export const MetaTitleComponent: React.FC<MetaTitleProps> = (props) => {
|
||||
...docInfo,
|
||||
doc: { ...getData() },
|
||||
locale: typeof locale === 'object' ? locale?.code : locale,
|
||||
} satisfies Parameters<GenerateTitle>[0]),
|
||||
} satisfies Omit<Parameters<GenerateTitle>[0], 'req'>),
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -49,7 +49,7 @@ export const PreviewComponent: React.FC<PreviewProps> = ({
|
||||
...docInfo,
|
||||
doc: { ...getData() },
|
||||
locale: typeof locale === 'object' ? locale?.code : locale,
|
||||
} satisfies Parameters<GenerateURL>[0]),
|
||||
} satisfies Omit<Parameters<GenerateURL>[0], 'req'>),
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -134,11 +134,12 @@ export const seoPlugin =
|
||||
{
|
||||
handler: async (req) => {
|
||||
await addDataAndFileToRequest(req)
|
||||
req.t
|
||||
|
||||
const result = pluginConfig.generateTitle
|
||||
? await pluginConfig.generateTitle(
|
||||
req.data as unknown as Parameters<GenerateTitle>[0],
|
||||
)
|
||||
? await pluginConfig.generateTitle({
|
||||
...req.data,
|
||||
req,
|
||||
} as unknown as Parameters<GenerateTitle>[0])
|
||||
: ''
|
||||
return new Response(JSON.stringify({ result }), { status: 200 })
|
||||
},
|
||||
@@ -148,10 +149,12 @@ export const seoPlugin =
|
||||
{
|
||||
handler: async (req) => {
|
||||
await addDataAndFileToRequest(req)
|
||||
|
||||
const result = pluginConfig.generateDescription
|
||||
? await pluginConfig.generateDescription(
|
||||
req.data as unknown as Parameters<GenerateDescription>[0],
|
||||
)
|
||||
? await pluginConfig.generateDescription({
|
||||
...req.data,
|
||||
req,
|
||||
} as unknown as Parameters<GenerateDescription>[0])
|
||||
: ''
|
||||
return new Response(JSON.stringify({ result }), { status: 200 })
|
||||
},
|
||||
@@ -161,8 +164,12 @@ export const seoPlugin =
|
||||
{
|
||||
handler: async (req) => {
|
||||
await addDataAndFileToRequest(req)
|
||||
|
||||
const result = pluginConfig.generateURL
|
||||
? await pluginConfig.generateURL(req.data as unknown as Parameters<GenerateURL>[0])
|
||||
? await pluginConfig.generateURL({
|
||||
...req.data,
|
||||
req,
|
||||
} as unknown as Parameters<GenerateURL>[0])
|
||||
: ''
|
||||
return new Response(JSON.stringify({ result }), { status: 200 })
|
||||
},
|
||||
@@ -172,10 +179,12 @@ export const seoPlugin =
|
||||
{
|
||||
handler: async (req) => {
|
||||
await addDataAndFileToRequest(req)
|
||||
|
||||
const result = pluginConfig.generateImage
|
||||
? await pluginConfig.generateImage(
|
||||
req.data as unknown as Parameters<GenerateImage>[0],
|
||||
)
|
||||
? await pluginConfig.generateImage({
|
||||
...req.data,
|
||||
req,
|
||||
} as unknown as Parameters<GenerateImage>[0])
|
||||
: ''
|
||||
return new Response(result, { status: 200 })
|
||||
},
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
import type { DocumentInfoContext } from '@payloadcms/ui'
|
||||
import type { Field, TextField, TextareaField, UploadField } from 'payload'
|
||||
import type { Field, PayloadRequest, TextField, TextareaField, UploadField } from 'payload'
|
||||
|
||||
export type GenerateTitle<T = any> = (
|
||||
args: { doc: T; locale?: string } & DocumentInfoContext,
|
||||
args: { doc: T; locale?: string; req: PayloadRequest } & DocumentInfoContext,
|
||||
) => Promise<string> | string
|
||||
|
||||
export type GenerateDescription<T = any> = (
|
||||
args: {
|
||||
doc: T
|
||||
locale?: string
|
||||
req: PayloadRequest
|
||||
} & DocumentInfoContext,
|
||||
) => Promise<string> | string
|
||||
|
||||
export type GenerateImage<T = any> = (
|
||||
args: { doc: T; locale?: string } & DocumentInfoContext,
|
||||
args: { doc: T; locale?: string; req: PayloadRequest } & DocumentInfoContext,
|
||||
) => Promise<string> | string
|
||||
|
||||
export type GenerateURL<T = any> = (
|
||||
args: { doc: T; locale?: string } & DocumentInfoContext,
|
||||
args: { doc: T; locale?: string; req: PayloadRequest } & DocumentInfoContext,
|
||||
) => Promise<string> | string
|
||||
|
||||
export type SEOPluginConfig = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-stripe",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Stripe plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-lexical",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The officially supported Lexical richtext adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
position: absolute;
|
||||
order: 3;
|
||||
left: unset;
|
||||
inset-inline-end: base(0.5);
|
||||
inset-inline-end: base(0.8);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: var(--theme-elevation-600);
|
||||
@@ -16,8 +16,8 @@
|
||||
border: none;
|
||||
|
||||
svg {
|
||||
width: base(0.75);
|
||||
height: base(0.75);
|
||||
width: base(0.8);
|
||||
height: base(0.8);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@@ -33,10 +33,11 @@
|
||||
|
||||
.toast-title {
|
||||
line-height: base(1);
|
||||
margin-right: base(1);
|
||||
}
|
||||
|
||||
.payload-toast-item {
|
||||
padding: base(0.5);
|
||||
padding: base(0.8);
|
||||
color: var(--theme-elevation-800);
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
@@ -69,8 +70,8 @@
|
||||
}
|
||||
|
||||
.toast-icon {
|
||||
width: base(1);
|
||||
height: base(1);
|
||||
width: base(0.8);
|
||||
height: base(0.8);
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -84,8 +85,8 @@
|
||||
|
||||
&.toast-warning {
|
||||
color: var(--theme-warning-800);
|
||||
border-color: var(--theme-warning-150);
|
||||
background-color: var(--theme-warning-50);
|
||||
border-color: var(--theme-warning-250);
|
||||
background-color: var(--theme-warning-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-warning-600);
|
||||
@@ -98,8 +99,8 @@
|
||||
|
||||
&.toast-error {
|
||||
color: var(--theme-error-800);
|
||||
border-color: var(--theme-error-150);
|
||||
background-color: var(--theme-error-50);
|
||||
border-color: var(--theme-error-250);
|
||||
background-color: var(--theme-error-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-error-600);
|
||||
@@ -112,8 +113,8 @@
|
||||
|
||||
&.toast-success {
|
||||
color: var(--theme-success-800);
|
||||
border-color: var(--theme-success-150);
|
||||
background-color: var(--theme-success-50);
|
||||
border-color: var(--theme-success-250);
|
||||
background-color: var(--theme-success-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-success-600);
|
||||
@@ -126,8 +127,8 @@
|
||||
|
||||
&.toast-info {
|
||||
color: var(--theme-elevation-800);
|
||||
border-color: var(--theme-elevation-150);
|
||||
background-color: var(--theme-elevation-50);
|
||||
border-color: var(--theme-elevation-250);
|
||||
background-color: var(--theme-elevation-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-elevation-600);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-slate",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "The officially supported Slate richtext adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
position: absolute;
|
||||
order: 3;
|
||||
left: unset;
|
||||
inset-inline-end: base(0.5);
|
||||
inset-inline-end: base(0.8);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: var(--theme-elevation-600);
|
||||
@@ -16,8 +16,8 @@
|
||||
border: none;
|
||||
|
||||
svg {
|
||||
width: base(0.75);
|
||||
height: base(0.75);
|
||||
width: base(0.8);
|
||||
height: base(0.8);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@@ -33,10 +33,11 @@
|
||||
|
||||
.toast-title {
|
||||
line-height: base(1);
|
||||
margin-right: base(1);
|
||||
}
|
||||
|
||||
.payload-toast-item {
|
||||
padding: base(0.5);
|
||||
padding: base(0.8);
|
||||
color: var(--theme-elevation-800);
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
@@ -69,8 +70,8 @@
|
||||
}
|
||||
|
||||
.toast-icon {
|
||||
width: base(1);
|
||||
height: base(1);
|
||||
width: base(0.8);
|
||||
height: base(0.8);
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -84,8 +85,8 @@
|
||||
|
||||
&.toast-warning {
|
||||
color: var(--theme-warning-800);
|
||||
border-color: var(--theme-warning-150);
|
||||
background-color: var(--theme-warning-50);
|
||||
border-color: var(--theme-warning-250);
|
||||
background-color: var(--theme-warning-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-warning-600);
|
||||
@@ -98,8 +99,8 @@
|
||||
|
||||
&.toast-error {
|
||||
color: var(--theme-error-800);
|
||||
border-color: var(--theme-error-150);
|
||||
background-color: var(--theme-error-50);
|
||||
border-color: var(--theme-error-250);
|
||||
background-color: var(--theme-error-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-error-600);
|
||||
@@ -112,8 +113,8 @@
|
||||
|
||||
&.toast-success {
|
||||
color: var(--theme-success-800);
|
||||
border-color: var(--theme-success-150);
|
||||
background-color: var(--theme-success-50);
|
||||
border-color: var(--theme-success-250);
|
||||
background-color: var(--theme-success-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-success-600);
|
||||
@@ -126,8 +127,8 @@
|
||||
|
||||
&.toast-info {
|
||||
color: var(--theme-elevation-800);
|
||||
border-color: var(--theme-elevation-150);
|
||||
background-color: var(--theme-elevation-50);
|
||||
border-color: var(--theme-elevation-250);
|
||||
background-color: var(--theme-elevation-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-elevation-600);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-azure",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Payload storage adapter for Azure Blob Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-gcs",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Payload storage adapter for Google Cloud Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-s3",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Payload storage adapter for Amazon S3",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-uploadthing",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Payload storage adapter for uploadthing",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-vercel-blob",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"description": "Payload storage adapter for Vercel Blob Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/translations",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/ui",
|
||||
"version": "3.0.0-beta.82",
|
||||
"version": "3.0.0-beta.84",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -224,7 +224,7 @@ export const Autosave: React.FC<Props> = ({
|
||||
if (autosaveTimeout) clearTimeout(autosaveTimeout)
|
||||
if (abortController.signal) {
|
||||
try {
|
||||
abortController.abort()
|
||||
abortController.abort('Autosave closed early.')
|
||||
} catch (error) {
|
||||
// swallow error
|
||||
}
|
||||
|
||||
@@ -13,13 +13,20 @@ const handleDragOver = (e: DragEvent) => {
|
||||
const baseClass = 'dropzone'
|
||||
|
||||
export type Props = {
|
||||
className?: string
|
||||
mimeTypes?: string[]
|
||||
onChange: (e: FileList) => void
|
||||
onPasteUrlClick?: () => void
|
||||
readonly className?: string
|
||||
readonly mimeTypes?: string[]
|
||||
readonly multipleFiles?: boolean
|
||||
readonly onChange: (e: FileList) => void
|
||||
readonly onPasteUrlClick?: () => void
|
||||
}
|
||||
|
||||
export const Dropzone: React.FC<Props> = ({ className, mimeTypes, onChange, onPasteUrlClick }) => {
|
||||
export const Dropzone: React.FC<Props> = ({
|
||||
className,
|
||||
mimeTypes,
|
||||
multipleFiles,
|
||||
onChange,
|
||||
onPasteUrlClick,
|
||||
}) => {
|
||||
const dropRef = React.useRef<HTMLDivElement>(null)
|
||||
const [dragging, setDragging] = React.useState(false)
|
||||
const inputRef = React.useRef(null)
|
||||
@@ -111,17 +118,21 @@ export const Dropzone: React.FC<Props> = ({ className, mimeTypes, onChange, onPa
|
||||
>
|
||||
{t('upload:selectFile')}
|
||||
</Button>
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
className={`${baseClass}__file-button`}
|
||||
onClick={onPasteUrlClick}
|
||||
size="medium"
|
||||
>
|
||||
{t('upload:pasteURL')}
|
||||
</Button>
|
||||
{typeof onPasteUrlClick === 'function' && (
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
className={`${baseClass}__file-button`}
|
||||
onClick={onPasteUrlClick}
|
||||
size="medium"
|
||||
>
|
||||
{t('upload:pasteURL')}
|
||||
</Button>
|
||||
)}
|
||||
<input
|
||||
accept={mimeTypes?.join(',')}
|
||||
aria-hidden="true"
|
||||
className={`${baseClass}__hidden-input`}
|
||||
multiple={multipleFiles}
|
||||
onChange={handleFileSelection}
|
||||
ref={inputRef}
|
||||
type="file"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
@import '../../scss/styles';
|
||||
|
||||
.id-label {
|
||||
font-size: base(0.75);
|
||||
font-size: base(0.8);
|
||||
line-height: base(1.2);
|
||||
font-weight: normal;
|
||||
color: var(--theme-elevation-600);
|
||||
background: var(--theme-elevation-100);
|
||||
padding: 0 base(0.6);
|
||||
padding: base(0.2) base(0.4);
|
||||
border-radius: $style-radius-m;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@import '../../scss/styles.scss';
|
||||
|
||||
.render-title {
|
||||
display: inline-flex;
|
||||
display: inline-block;
|
||||
&__id {
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
|
||||
@@ -109,15 +109,7 @@ export const Upload: React.FC<UploadProps> = (props) => {
|
||||
const handleFileChange = useCallback(
|
||||
(newFile: File) => {
|
||||
if (newFile instanceof File) {
|
||||
const fileReader = new FileReader()
|
||||
fileReader.onload = (e) => {
|
||||
const imgSrc = e.target?.result
|
||||
|
||||
if (typeof imgSrc === 'string') {
|
||||
setFileSrc(imgSrc)
|
||||
}
|
||||
}
|
||||
fileReader.readAsDataURL(newFile)
|
||||
setFileSrc(URL.createObjectURL(newFile))
|
||||
}
|
||||
|
||||
setValue(newFile)
|
||||
@@ -202,6 +194,9 @@ export const Upload: React.FC<UploadProps> = (props) => {
|
||||
|
||||
useEffect(() => {
|
||||
setDoc(reduceFieldsToValues(initialState || {}, true))
|
||||
if (initialState?.file?.value instanceof File) {
|
||||
setFileSrc(URL.createObjectURL(initialState.file.value))
|
||||
}
|
||||
setReplacingFile(false)
|
||||
}, [initialState])
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ export { Collapsible } from '../../elements/Collapsible/index.js'
|
||||
export { CopyToClipboard } from '../../elements/CopyToClipboard/index.js'
|
||||
export { DeleteMany } from '../../elements/DeleteMany/index.js'
|
||||
export { DocumentControls } from '../../elements/DocumentControls/index.js'
|
||||
export { Dropzone } from '../../elements/Dropzone/index.js'
|
||||
export { useDocumentDrawer } from '../../elements/DocumentDrawer/index.js'
|
||||
export { DocumentFields } from '../../elements/DocumentFields/index.js'
|
||||
export { Drawer, DrawerToggler, formatDrawerSlug } from '../../elements/Drawer/index.js'
|
||||
|
||||
@@ -26,6 +26,6 @@ export const ChevronIcon: React.FC<{
|
||||
width={20}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path className="stroke" d="M6 9L10 13L14 9" strokeLinecap="square" />
|
||||
<path className="stroke" d="M6 8L10 12.5L14 8" strokeLinecap="square" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
@@ -13,7 +13,8 @@ export const LogOutIcon: React.FC = () => (
|
||||
>
|
||||
<path
|
||||
className="stroke"
|
||||
d="M8 16H5.33333C4.97971 16 4.64057 15.8595 4.39052 15.6095C4.14048 15.3594 4 15.0203 4 14.6667V5.33333C4 4.97971 4.14048 4.64057 4.39052 4.39052C4.64057 4.14048 4.97971 4 5.33333 4H8M12.6667 13.3333L16 10M16 10L12.6667 6.66667M16 10H8"
|
||||
d="M12 16H14.6667C15.0203 16 15.3594 15.8595 15.6095 15.6095C15.8595 15.3594 16 15.0203 16 14.6667V5.33333C16 4.97971 15.8595 4.64057 15.6095 4.39052C15.3594 4.14048 15.0203 4 14.6667 4H12M7.33333 13.3333L4 10M4 10L7.33333 6.66667M4 10H12"
|
||||
strokeLinecap="square"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
|
||||
@@ -263,6 +263,11 @@ export function AuthProvider({
|
||||
}
|
||||
}, [debouncedLocationChange, refreshCookie, id])
|
||||
|
||||
// When initialUser changes, reset in state
|
||||
useEffect(() => {
|
||||
setUser(initialUser)
|
||||
}, [initialUser])
|
||||
|
||||
useEffect(() => {
|
||||
setLastLocationChange(Date.now())
|
||||
}, [pathname])
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
position: absolute;
|
||||
order: 3;
|
||||
left: unset;
|
||||
inset-inline-end: base(0.5);
|
||||
inset-inline-end: base(0.8);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: var(--theme-elevation-600);
|
||||
@@ -16,8 +16,8 @@
|
||||
border: none;
|
||||
|
||||
svg {
|
||||
width: base(0.75);
|
||||
height: base(0.75);
|
||||
width: base(0.8);
|
||||
height: base(0.8);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@@ -33,10 +33,11 @@
|
||||
|
||||
.toast-title {
|
||||
line-height: base(1);
|
||||
margin-right: base(1);
|
||||
}
|
||||
|
||||
.payload-toast-item {
|
||||
padding: base(0.5);
|
||||
padding: base(0.8);
|
||||
color: var(--theme-elevation-800);
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
@@ -69,8 +70,8 @@
|
||||
}
|
||||
|
||||
.toast-icon {
|
||||
width: base(1);
|
||||
height: base(1);
|
||||
width: base(0.8);
|
||||
height: base(0.8);
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -84,8 +85,8 @@
|
||||
|
||||
&.toast-warning {
|
||||
color: var(--theme-warning-800);
|
||||
border-color: var(--theme-warning-150);
|
||||
background-color: var(--theme-warning-50);
|
||||
border-color: var(--theme-warning-250);
|
||||
background-color: var(--theme-warning-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-warning-600);
|
||||
@@ -98,8 +99,8 @@
|
||||
|
||||
&.toast-error {
|
||||
color: var(--theme-error-800);
|
||||
border-color: var(--theme-error-150);
|
||||
background-color: var(--theme-error-50);
|
||||
border-color: var(--theme-error-250);
|
||||
background-color: var(--theme-error-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-error-600);
|
||||
@@ -112,8 +113,8 @@
|
||||
|
||||
&.toast-success {
|
||||
color: var(--theme-success-800);
|
||||
border-color: var(--theme-success-150);
|
||||
background-color: var(--theme-success-50);
|
||||
border-color: var(--theme-success-250);
|
||||
background-color: var(--theme-success-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-success-600);
|
||||
@@ -126,8 +127,8 @@
|
||||
|
||||
&.toast-info {
|
||||
color: var(--theme-elevation-800);
|
||||
border-color: var(--theme-elevation-150);
|
||||
background-color: var(--theme-elevation-50);
|
||||
border-color: var(--theme-elevation-250);
|
||||
background-color: var(--theme-elevation-100);
|
||||
|
||||
.payload-toast-close-button {
|
||||
color: var(--theme-elevation-600);
|
||||
|
||||
@@ -120,7 +120,7 @@ describe('auth', () => {
|
||||
await ensureCompilationIsDone({ page, serverURL })
|
||||
})
|
||||
|
||||
describe('authenticated users', () => {
|
||||
describe('passwords', () => {
|
||||
beforeAll(() => {
|
||||
url = new AdminUrlUtil(serverURL, slug)
|
||||
})
|
||||
@@ -155,6 +155,29 @@ describe('auth', () => {
|
||||
await expect(page.locator('#field-email')).toHaveValue(emailBeforeSave)
|
||||
})
|
||||
|
||||
test('should prevent new user creation without confirm password', async () => {
|
||||
await page.goto(url.create)
|
||||
await page.locator('#field-email').fill('dev2@payloadcms.com')
|
||||
await page.locator('#field-password').fill('password')
|
||||
// should fail to save without confirm password
|
||||
await page.locator('#action-save').click()
|
||||
await expect(
|
||||
page.locator('.field-type.confirm-password .tooltip--show', {
|
||||
hasText: exactText('This field is required.'),
|
||||
}),
|
||||
).toBeVisible()
|
||||
|
||||
// should succeed with matching confirm password
|
||||
await page.locator('#field-confirm-password').fill('password')
|
||||
await saveDocAndAssert(page, '#action-save')
|
||||
})
|
||||
})
|
||||
|
||||
describe('authenticated users', () => {
|
||||
beforeAll(() => {
|
||||
url = new AdminUrlUtil(serverURL, slug)
|
||||
})
|
||||
|
||||
test('should have up-to-date user in `useAuth` hook', async () => {
|
||||
await page.goto(url.account)
|
||||
await page.waitForURL(url.account)
|
||||
|
||||
Reference in New Issue
Block a user