diff --git a/packages/plugin-seo/src/fields/MetaDescription.tsx b/packages/plugin-seo/src/fields/MetaDescription.tsx index d4714c7a34..6f8b0a241e 100644 --- a/packages/plugin-seo/src/fields/MetaDescription.tsx +++ b/packages/plugin-seo/src/fields/MetaDescription.tsx @@ -1,21 +1,22 @@ import React, { useCallback } from 'react'; -import { Props as TextFieldType } from 'payload/dist/admin/components/forms/field-types/Text/types'; import { useField, useWatchForm } from 'payload/components/forms'; import { FieldType, Options } from 'payload/dist/admin/components/forms/useField/types'; import { LengthIndicator } from '../ui/LengthIndicator'; import { defaults } from '../defaults'; import TextareaInput from 'payload/dist/admin/components/forms/field-types/Textarea/Input'; +import { TextareaField } from 'payload/dist/fields/config/types'; const { minLength, maxLength, } = defaults.description; -export const MetaDescription: React.FC = (props) => { +export const MetaDescription: React.FC = (props) => { + // TODO: this temporary until payload types are updated for custom field props const { label, name - } = props; + } = props as TextareaField || {}; const { fields } = useWatchForm(); diff --git a/packages/plugin-seo/src/fields/MetaImage.tsx b/packages/plugin-seo/src/fields/MetaImage.tsx index 0a0be86c4d..35786b92c0 100644 --- a/packages/plugin-seo/src/fields/MetaImage.tsx +++ b/packages/plugin-seo/src/fields/MetaImage.tsx @@ -6,13 +6,14 @@ import { useField, useWatchForm } from 'payload/components/forms'; import { FieldType, Options } from 'payload/dist/admin/components/forms/useField/types'; import { Pill } from '../ui/Pill'; -export const MetaImage: React.FC = (props) => { +export const MetaImage: React.FC = (props) => { + // TODO: this temporary until payload types are updated for custom field props const { label, relationTo, fieldTypes, name, - } = props; + } = props as UploadFieldType || {}; const field: FieldType = useField(props as Options); @@ -42,7 +43,7 @@ export const MetaImage: React.FC = (props) => { const hasImage = Boolean(value); - const config = useConfig(); // TODO: this returns an empty object + const config = useConfig(); const { collections, diff --git a/packages/plugin-seo/src/fields/MetaTitle.tsx b/packages/plugin-seo/src/fields/MetaTitle.tsx index 282ee4834e..87fca2ac7e 100644 --- a/packages/plugin-seo/src/fields/MetaTitle.tsx +++ b/packages/plugin-seo/src/fields/MetaTitle.tsx @@ -11,11 +11,12 @@ const { maxLength, } = defaults.title; -export const MetaTitle: React.FC = (props) => { +export const MetaTitle: React.FC = (props) => { + // TODO: this temporary until payload types are updated for custom field props const { label, name - } = props; + } = props as TextFieldType || {}; const field: FieldType = useField(props as Options); diff --git a/packages/plugin-seo/src/index.ts b/packages/plugin-seo/src/index.ts index a5d66b532e..4d37a6826a 100644 --- a/packages/plugin-seo/src/index.ts +++ b/packages/plugin-seo/src/index.ts @@ -1,87 +1,92 @@ import { Config } from 'payload/config'; -import { CollectionConfig } from 'payload/dist/collections/config/types'; import { MetaDescription } from './fields/MetaDescription'; import { Overview } from './ui/Overview'; import { MetaTitle } from './fields/MetaTitle'; import { Preview } from './ui/Preview'; import { MetaImage } from './fields/MetaImage'; import { SEOConfig } from './types'; +import { Field } from 'payload/dist/fields/config/types'; -const seo = (seoConfig: SEOConfig) => (config: Config): Config => ({ - ...config, - collections: config.collections?.map((collection) => { - const { slug } = collection; - const isEnabled = seoConfig?.collections?.includes(slug); - - if (isEnabled) { - return ({ - ...collection, - fields: [ - ...collection?.fields || [], - { - name: 'meta', - label: 'SEO', - type: 'group', - fields: [ - { - name: 'overview', - label: 'Overview', - type: 'ui', - admin: { - components: { - Field: Overview, - }, - }, - }, - { - name: 'title', - label: 'Meta Title', - type: 'text', - admin: { - components: { - Field: MetaTitle, - }, - }, - }, - { - name: 'description', - label: 'Meta Description', - type: 'textarea', - admin: { - components: { - Field: MetaDescription, - }, - }, - }, - { - name: 'image', - label: 'Meta Image', - type: 'upload', - relationTo: seoConfig?.uploadsCollection || '', - admin: { - description: 'Maximum upload file size: 12MB. Recommended file size for images is <500KB.', - components: { - Field: MetaImage, - }, - }, - }, - { - name: 'preview', - label: 'Preview', - type: 'ui', - admin: { - components: { - Field: Preview, - }, - }, - }, - ], +const seo = (seoConfig: SEOConfig) => (config: Config): Config => { + const seoFields: Field[] = [ + { + name: 'meta', + label: 'SEO', + type: 'group', + fields: [ + { + name: 'overview', + label: 'Overview', + type: 'ui', + admin: { + components: { + Field: Overview, + }, }, - ], - }) as CollectionConfig; + }, + { + name: 'title', + type: 'text', + admin: { + components: { + Field: MetaTitle, + }, + }, + }, + { + name: 'description', + label: 'Meta Description', + type: 'textarea', + admin: { + components: { + Field: MetaDescription, + }, + }, + }, + ...seoConfig?.uploadsCollection ? [{ + name: 'image', + label: 'Meta Image', + type: 'upload', + relationTo: seoConfig?.uploadsCollection, + admin: { + description: 'Maximum upload file size: 12MB. Recommended file size for images is <500KB.', + components: { + Field: MetaImage, + }, + }, + } as Field] : [], + { + name: 'preview', + label: 'Preview', + type: 'ui', + admin: { + components: { + Field: Preview, + }, + }, + }, + ] } - return collection; - }), -}); + ] + + return ({ + ...config, + collections: config.collections?.map((collection) => { + const { slug } = collection; + const isEnabled = seoConfig?.collections?.includes(slug); + + if (isEnabled) { + return ({ + ...collection, + fields: [ + ...collection?.fields || [], + ...seoFields, + ], + }) + } + return collection; + }) || [] + }) +}; export default seo; diff --git a/packages/plugin-seo/src/types.ts b/packages/plugin-seo/src/types.ts index 5212af74e5..06745b6af1 100644 --- a/packages/plugin-seo/src/types.ts +++ b/packages/plugin-seo/src/types.ts @@ -1,6 +1,10 @@ +import { Field } from "payload/dist/fields/config/types"; + export type SEOConfig = { collections?: string[] uploadsCollection?: string + fields?: Partial[] generateTitle?: (args: { doc: any }) => string | Promise generateDescription?: (args: { doc: any }) => string | Promise + generateImage?: (args: { doc: any }) => string | Promise } diff --git a/packages/plugin-seo/src/ui/Overview.tsx b/packages/plugin-seo/src/ui/Overview.tsx index c26566783d..70a83963df 100644 --- a/packages/plugin-seo/src/ui/Overview.tsx +++ b/packages/plugin-seo/src/ui/Overview.tsx @@ -1,8 +1,6 @@ -/* eslint-disable no-use-before-define */ -/* eslint-disable import/no-extraneous-dependencies */ // import { Button } from 'payload/components'; import { useForm, useWatchForm } from 'payload/components/forms'; -// import { FormContext } from 'payload/dist/admin/components/forms/Form/context'; +import { Field } from 'payload/dist/admin/components/forms/Form/types'; import React, { useCallback, useState, useEffect } from 'react'; import { defaults } from '../defaults'; @@ -27,13 +25,13 @@ export const Overview: React.FC = () => { fields: { 'meta.title': { value: metaTitle, - }, + } = {} as Field, 'meta.description': { value: metaDesc, - }, + } = {} as Field, 'meta.image': { value: metaImage, - }, + } = {} as Field, }, } = useWatchForm(); diff --git a/packages/plugin-seo/src/ui/Preview.tsx b/packages/plugin-seo/src/ui/Preview.tsx index 1cf3a6fb70..947368cb86 100644 --- a/packages/plugin-seo/src/ui/Preview.tsx +++ b/packages/plugin-seo/src/ui/Preview.tsx @@ -1,7 +1,6 @@ -/* eslint-disable no-use-before-define */ -/* eslint-disable import/no-extraneous-dependencies */ import { useWatchForm } from 'payload/components/forms'; import React from 'react'; +import { Field } from 'payload/dist/admin/components/forms/Form/types'; export const Preview: React.FC = () => { const { fields } = useWatchForm(); @@ -9,10 +8,10 @@ export const Preview: React.FC = () => { const { 'meta.title': { value: metaTitle, - }, + } = {} as Field, 'meta.description': { value: metaDescription, - }, + } = {} as Field, } = fields; return (