fix(plugin-seo)!: data types plugin seo (#6979)
Changed the data to correctly match type generic being sent to the
generate functions. So now you can type your generateTitle etc.
functions like this
```ts
// before
const generateTitle: GenerateTitle = async <Page>({ doc, locale }) => {
return `Website.com — ${doc?.title?.value}`
}
// curent
import type { GenerateDescription, GenerateTitle, GenerateURL } from '@payloadcms/plugin-seo/types'
import type { Page } from './payload-types'
const generateTitle: GenerateTitle<Page> = async ({ doc, locale }) => {
return `Website.com — ${doc?.title}`
}
const generateDescription: GenerateDescription<Page> = async ({ doc, locale }) => {
return doc?.excerpt || 'generated description'
}
const generateURL: GenerateURL<Page> = async ({ doc, locale }) => {
return `https://yoursite.com/${locale ? locale + '/' : ''}${doc?.slug || ''}`
}
```
Breaking change because it was previously a FormState value.
This commit is contained in:
@@ -5,10 +5,10 @@ import type { FieldType, FormFieldBase, Options } from '@payloadcms/ui'
|
|||||||
import {
|
import {
|
||||||
FieldLabel,
|
FieldLabel,
|
||||||
TextareaInput,
|
TextareaInput,
|
||||||
useAllFormFields,
|
|
||||||
useDocumentInfo,
|
useDocumentInfo,
|
||||||
useField,
|
useField,
|
||||||
useFieldProps,
|
useFieldProps,
|
||||||
|
useForm,
|
||||||
useLocale,
|
useLocale,
|
||||||
useTranslation,
|
useTranslation,
|
||||||
} from '@payloadcms/ui'
|
} from '@payloadcms/ui'
|
||||||
@@ -35,7 +35,7 @@ export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
|
|||||||
const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()
|
const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()
|
||||||
|
|
||||||
const locale = useLocale()
|
const locale = useLocale()
|
||||||
const [fields] = useAllFormFields()
|
const { getData } = useForm()
|
||||||
const docInfo = useDocumentInfo()
|
const docInfo = useDocumentInfo()
|
||||||
|
|
||||||
const field: FieldType<string> = useField({
|
const field: FieldType<string> = useField({
|
||||||
@@ -50,7 +50,7 @@ export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
|
|||||||
const genDescriptionResponse = await fetch('/api/plugin-seo/generate-description', {
|
const genDescriptionResponse = await fetch('/api/plugin-seo/generate-description', {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
...docInfo,
|
...docInfo,
|
||||||
doc: { ...fields },
|
doc: { ...getData() },
|
||||||
locale: typeof locale === 'object' ? locale?.code : locale,
|
locale: typeof locale === 'object' ? locale?.code : locale,
|
||||||
} satisfies Parameters<GenerateDescription>[0]),
|
} satisfies Parameters<GenerateDescription>[0]),
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
@@ -63,7 +63,7 @@ export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
|
|||||||
const { result: generatedDescription } = await genDescriptionResponse.json()
|
const { result: generatedDescription } = await genDescriptionResponse.json()
|
||||||
|
|
||||||
setValue(generatedDescription || '')
|
setValue(generatedDescription || '')
|
||||||
}, [fields, setValue, hasGenerateDescriptionFn, locale, docInfo])
|
}, [hasGenerateDescriptionFn, docInfo, getData, locale, setValue])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import type { FieldType, Options, UploadInputProps } from '@payloadcms/ui'
|
|||||||
import {
|
import {
|
||||||
FieldLabel,
|
FieldLabel,
|
||||||
UploadInput,
|
UploadInput,
|
||||||
useAllFormFields,
|
|
||||||
useConfig,
|
useConfig,
|
||||||
useDocumentInfo,
|
useDocumentInfo,
|
||||||
useField,
|
useField,
|
||||||
|
useForm,
|
||||||
useLocale,
|
useLocale,
|
||||||
useTranslation,
|
useTranslation,
|
||||||
} from '@payloadcms/ui'
|
} from '@payloadcms/ui'
|
||||||
@@ -32,7 +32,7 @@ export const MetaImage: React.FC<MetaImageProps> = (props) => {
|
|||||||
const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()
|
const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()
|
||||||
|
|
||||||
const locale = useLocale()
|
const locale = useLocale()
|
||||||
const [fields] = useAllFormFields()
|
const { getData } = useForm()
|
||||||
const docInfo = useDocumentInfo()
|
const docInfo = useDocumentInfo()
|
||||||
|
|
||||||
const { errorMessage, setValue, showError, value } = field
|
const { errorMessage, setValue, showError, value } = field
|
||||||
@@ -43,7 +43,7 @@ export const MetaImage: React.FC<MetaImageProps> = (props) => {
|
|||||||
const genImageResponse = await fetch('/api/plugin-seo/generate-image', {
|
const genImageResponse = await fetch('/api/plugin-seo/generate-image', {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
...docInfo,
|
...docInfo,
|
||||||
doc: { ...fields },
|
doc: { ...getData() },
|
||||||
locale: typeof locale === 'object' ? locale?.code : locale,
|
locale: typeof locale === 'object' ? locale?.code : locale,
|
||||||
} satisfies Parameters<GenerateImage>[0]),
|
} satisfies Parameters<GenerateImage>[0]),
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
@@ -56,7 +56,7 @@ export const MetaImage: React.FC<MetaImageProps> = (props) => {
|
|||||||
const { result: generatedImage } = await genImageResponse.json()
|
const { result: generatedImage } = await genImageResponse.json()
|
||||||
|
|
||||||
setValue(generatedImage || '')
|
setValue(generatedImage || '')
|
||||||
}, [fields, setValue, hasGenerateImageFn, locale, docInfo])
|
}, [hasGenerateImageFn, docInfo, getData, locale, setValue])
|
||||||
|
|
||||||
const hasImage = Boolean(value)
|
const hasImage = Boolean(value)
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import type { FieldType, FormFieldBase, Options } from '@payloadcms/ui'
|
|||||||
import {
|
import {
|
||||||
FieldLabel,
|
FieldLabel,
|
||||||
TextInput,
|
TextInput,
|
||||||
useAllFormFields,
|
|
||||||
useDocumentInfo,
|
useDocumentInfo,
|
||||||
useField,
|
useField,
|
||||||
useFieldProps,
|
useFieldProps,
|
||||||
|
useForm,
|
||||||
useLocale,
|
useLocale,
|
||||||
useTranslation,
|
useTranslation,
|
||||||
} from '@payloadcms/ui'
|
} from '@payloadcms/ui'
|
||||||
@@ -39,7 +39,7 @@ export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
|
|||||||
} as Options)
|
} as Options)
|
||||||
|
|
||||||
const locale = useLocale()
|
const locale = useLocale()
|
||||||
const [fields] = useAllFormFields()
|
const { getData } = useForm()
|
||||||
const docInfo = useDocumentInfo()
|
const docInfo = useDocumentInfo()
|
||||||
|
|
||||||
const { errorMessage, setValue, showError, value } = field
|
const { errorMessage, setValue, showError, value } = field
|
||||||
@@ -50,7 +50,7 @@ export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
|
|||||||
const genTitleResponse = await fetch('/api/plugin-seo/generate-title', {
|
const genTitleResponse = await fetch('/api/plugin-seo/generate-title', {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
...docInfo,
|
...docInfo,
|
||||||
doc: { ...fields },
|
doc: { ...getData() },
|
||||||
locale: typeof locale === 'object' ? locale?.code : locale,
|
locale: typeof locale === 'object' ? locale?.code : locale,
|
||||||
} satisfies Parameters<GenerateTitle>[0]),
|
} satisfies Parameters<GenerateTitle>[0]),
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
@@ -63,7 +63,7 @@ export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
|
|||||||
const { result: generatedTitle } = await genTitleResponse.json()
|
const { result: generatedTitle } = await genTitleResponse.json()
|
||||||
|
|
||||||
setValue(generatedTitle || '')
|
setValue(generatedTitle || '')
|
||||||
}, [fields, setValue, hasGenerateTitleFn, locale, docInfo])
|
}, [hasGenerateTitleFn, docInfo, getData, locale, setValue])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
import type { DocumentInfoContext } from '@payloadcms/ui'
|
import type { DocumentInfoContext } from '@payloadcms/ui'
|
||||||
import type { Field, TextField, TextareaField, UploadField } from 'payload'
|
import type { Field, TextField, TextareaField, UploadField } from 'payload'
|
||||||
|
|
||||||
export type GenerateTitle = <T = any>(
|
export type GenerateTitle<T = any> = (
|
||||||
args: DocumentInfoContext & { doc: T; locale?: string },
|
args: DocumentInfoContext & { doc: T; locale?: string },
|
||||||
) => Promise<string> | string
|
) => Promise<string> | string
|
||||||
|
|
||||||
export type GenerateDescription = <T = any>(
|
export type GenerateDescription<T = any> = (
|
||||||
args: DocumentInfoContext & {
|
args: DocumentInfoContext & {
|
||||||
doc: T
|
doc: T
|
||||||
locale?: string
|
locale?: string
|
||||||
},
|
},
|
||||||
) => Promise<string> | string
|
) => Promise<string> | string
|
||||||
|
|
||||||
export type GenerateImage = <T = any>(
|
export type GenerateImage<T = any> = (
|
||||||
args: DocumentInfoContext & { doc: T; locale?: string },
|
args: DocumentInfoContext & { doc: T; locale?: string },
|
||||||
) => Promise<string> | string
|
) => Promise<string> | string
|
||||||
|
|
||||||
export type GenerateURL = <T = any>(
|
export type GenerateURL<T = any> = (
|
||||||
args: DocumentInfoContext & { doc: T; locale?: string },
|
args: DocumentInfoContext & { doc: T; locale?: string },
|
||||||
) => Promise<string> | string
|
) => Promise<string> | string
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,13 @@
|
|||||||
|
|
||||||
import type { FormField, UIField } from 'payload'
|
import type { FormField, UIField } from 'payload'
|
||||||
|
|
||||||
import { useAllFormFields, useDocumentInfo, useLocale, useTranslation } from '@payloadcms/ui'
|
import {
|
||||||
|
useAllFormFields,
|
||||||
|
useDocumentInfo,
|
||||||
|
useForm,
|
||||||
|
useLocale,
|
||||||
|
useTranslation,
|
||||||
|
} from '@payloadcms/ui'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
|
||||||
import type { PluginSEOTranslationKeys, PluginSEOTranslations } from '../translations/index.js'
|
import type { PluginSEOTranslationKeys, PluginSEOTranslations } from '../translations/index.js'
|
||||||
@@ -17,6 +23,7 @@ export const Preview: React.FC<PreviewProps> = ({ hasGenerateURLFn }) => {
|
|||||||
|
|
||||||
const locale = useLocale()
|
const locale = useLocale()
|
||||||
const [fields] = useAllFormFields()
|
const [fields] = useAllFormFields()
|
||||||
|
const { getData } = useForm()
|
||||||
const docInfo = useDocumentInfo()
|
const docInfo = useDocumentInfo()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -31,7 +38,7 @@ export const Preview: React.FC<PreviewProps> = ({ hasGenerateURLFn }) => {
|
|||||||
const genURLResponse = await fetch('/api/plugin-seo/generate-url', {
|
const genURLResponse = await fetch('/api/plugin-seo/generate-url', {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
...docInfo,
|
...docInfo,
|
||||||
doc: { ...fields },
|
doc: { ...getData() },
|
||||||
locale: typeof locale === 'object' ? locale?.code : locale,
|
locale: typeof locale === 'object' ? locale?.code : locale,
|
||||||
} satisfies Parameters<GenerateURL>[0]),
|
} satisfies Parameters<GenerateURL>[0]),
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
@@ -49,7 +56,7 @@ export const Preview: React.FC<PreviewProps> = ({ hasGenerateURLFn }) => {
|
|||||||
if (hasGenerateURLFn && !href) {
|
if (hasGenerateURLFn && !href) {
|
||||||
void getHref()
|
void getHref()
|
||||||
}
|
}
|
||||||
}, [fields, href, locale, docInfo, hasGenerateURLFn])
|
}, [fields, href, locale, docInfo, hasGenerateURLFn, getData])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import { fileURLToPath } from 'node:url'
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
const dirname = path.dirname(filename)
|
const dirname = path.dirname(filename)
|
||||||
|
import type { GenerateDescription, GenerateTitle, GenerateURL } from '@payloadcms/plugin-seo/types'
|
||||||
|
import type { Page } from 'plugin-seo/payload-types.js'
|
||||||
|
|
||||||
import { seoPlugin } from '@payloadcms/plugin-seo'
|
import { seoPlugin } from '@payloadcms/plugin-seo'
|
||||||
import { en } from '@payloadcms/translations/languages/en'
|
import { en } from '@payloadcms/translations/languages/en'
|
||||||
import { es } from '@payloadcms/translations/languages/es'
|
import { es } from '@payloadcms/translations/languages/es'
|
||||||
@@ -13,6 +16,18 @@ import { Pages } from './collections/Pages.js'
|
|||||||
import { Users } from './collections/Users.js'
|
import { Users } from './collections/Users.js'
|
||||||
import { seed } from './seed/index.js'
|
import { seed } from './seed/index.js'
|
||||||
|
|
||||||
|
const generateTitle: GenerateTitle<Page> = ({ doc }) => {
|
||||||
|
return `Website.com — ${doc?.title}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateDescription: GenerateDescription<Page> = ({ doc }) => {
|
||||||
|
return doc?.excerpt || 'generated description'
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateURL: GenerateURL<Page> = ({ doc, locale }) => {
|
||||||
|
return `https://yoursite.com/${locale ? locale + '/' : ''}${doc?.slug || ''}`
|
||||||
|
}
|
||||||
|
|
||||||
export default buildConfigWithDefaults({
|
export default buildConfigWithDefaults({
|
||||||
collections: [Users, Pages, Media],
|
collections: [Users, Pages, Media],
|
||||||
i18n: {
|
i18n: {
|
||||||
@@ -59,10 +74,9 @@ export default buildConfigWithDefaults({
|
|||||||
label: 'og:title',
|
label: 'og:title',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
generateDescription: ({ doc }: any) => doc?.excerpt?.value || 'generated description',
|
generateDescription,
|
||||||
generateTitle: (data: any) => `Website.com — ${data?.doc?.title?.value}`,
|
generateTitle,
|
||||||
generateURL: ({ doc, locale }: any) =>
|
generateURL,
|
||||||
`https://yoursite.com/${locale ? locale + '/' : ''}${doc?.slug?.value || ''}`,
|
|
||||||
tabbedUI: true,
|
tabbedUI: true,
|
||||||
uploadsCollection: 'media',
|
uploadsCollection: 'media',
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -46,9 +46,11 @@ export interface Page {
|
|||||||
title: string;
|
title: string;
|
||||||
excerpt?: string | null;
|
excerpt?: string | null;
|
||||||
slug: string;
|
slug: string;
|
||||||
meta?: {
|
meta: {
|
||||||
title?: string | null;
|
title: string;
|
||||||
description?: string | null;
|
description?: string | null;
|
||||||
|
image?: string | Media | null;
|
||||||
|
ogTitle?: string | null;
|
||||||
};
|
};
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user