feat(plugin-search)!: make search collection fields override into a function that provides defaultFields inline with other plugins (#7095)
searchPlugin's searchOverrides for the collection now takes in a fields
function instead of array similar to other plugins and patterns we use
to allow you to map over existing fields as well if needed.
```ts
// before
searchPlugin({
searchOverrides: {
slug: 'search-results',
fields: [
{
name: 'excerpt',
type: 'textarea',
admin: {
position: 'sidebar',
},
},
]
},
}),
// current
searchPlugin({
searchOverrides: {
slug: 'search-results',
fields: ({ defaultFields }) => [
...defaultFields,
{
name: 'excerpt',
type: 'textarea',
admin: {
position: 'sidebar',
},
},
]
},
}),
```
This commit is contained in:
@@ -104,6 +104,8 @@ The `defaultPriorities` property is used to set a fallback `priority` on search
|
||||
|
||||
This plugin automatically creates the `search` collection, but you can override anything on this collection via the `searchOverrides` property. It accepts anything from the [Payload Collection Config](https://payloadcms.com/docs/configuration/collections) and merges it in with the default `search` collection config provided by the plugin.
|
||||
|
||||
Note that the `fields` property is a function that receives an object with a `defaultFields` key. This is an array of fields that are automatically added to the `search` collection. You can modify this array or add new fields to it.
|
||||
|
||||
```ts
|
||||
// payload.config.ts
|
||||
{
|
||||
@@ -111,6 +113,16 @@ This plugin automatically creates the `search` collection, but you can override
|
||||
searchPlugin({
|
||||
searchOverrides: {
|
||||
slug: 'search-results',
|
||||
fields: ({ defaultFields }) => [
|
||||
...defaultFields,
|
||||
{
|
||||
name: 'excerpt',
|
||||
type: 'textarea',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import type { CollectionConfig, Field } from 'payload'
|
||||
|
||||
import deepMerge from 'deepmerge'
|
||||
|
||||
@@ -7,63 +7,75 @@ import type { SearchPluginConfig } from '../types.js'
|
||||
import { LinkToDoc } from './ui/index.js'
|
||||
|
||||
// all settings can be overridden by the config
|
||||
export const generateSearchCollection = (pluginConfig: SearchPluginConfig): CollectionConfig =>
|
||||
deepMerge(
|
||||
export const generateSearchCollection = (pluginConfig: SearchPluginConfig): CollectionConfig => {
|
||||
const defaultFields: Field[] = [
|
||||
{
|
||||
slug: 'search',
|
||||
access: {
|
||||
create: (): boolean => false,
|
||||
read: (): boolean => true,
|
||||
},
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
admin: {
|
||||
defaultColumns: ['title'],
|
||||
description:
|
||||
'This is a collection of automatically created search results. These results are used by the global site search and will be updated automatically as documents in the CMS are created or updated.',
|
||||
enableRichTextRelationship: false,
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
admin: {
|
||||
readOnly: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
type: 'number',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'doc',
|
||||
type: 'relationship',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
readOnly: true,
|
||||
},
|
||||
index: true,
|
||||
maxDepth: 0,
|
||||
relationTo: pluginConfig?.collections || [],
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'docUrl',
|
||||
type: 'ui',
|
||||
admin: {
|
||||
components: {
|
||||
Field: LinkToDoc,
|
||||
},
|
||||
position: 'sidebar',
|
||||
},
|
||||
},
|
||||
],
|
||||
labels: {
|
||||
plural: 'Search Results',
|
||||
singular: 'Search Result',
|
||||
readOnly: true,
|
||||
},
|
||||
},
|
||||
pluginConfig?.searchOverrides || {},
|
||||
)
|
||||
{
|
||||
name: 'priority',
|
||||
type: 'number',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'doc',
|
||||
type: 'relationship',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
readOnly: true,
|
||||
},
|
||||
index: true,
|
||||
maxDepth: 0,
|
||||
relationTo: pluginConfig?.collections || [],
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'docUrl',
|
||||
type: 'ui',
|
||||
admin: {
|
||||
components: {
|
||||
Field: LinkToDoc,
|
||||
},
|
||||
position: 'sidebar',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const newConfig: CollectionConfig = {
|
||||
...(pluginConfig?.searchOverrides || {}),
|
||||
slug: pluginConfig?.searchOverrides?.slug || 'search',
|
||||
access: {
|
||||
create: (): boolean => false,
|
||||
read: (): boolean => true,
|
||||
...(pluginConfig?.searchOverrides?.access || {}),
|
||||
},
|
||||
admin: {
|
||||
defaultColumns: ['title'],
|
||||
description:
|
||||
'This is a collection of automatically created search results. These results are used by the global site search and will be updated automatically as documents in the CMS are created or updated.',
|
||||
enableRichTextRelationship: false,
|
||||
useAsTitle: 'title',
|
||||
...(pluginConfig?.searchOverrides?.admin || {}),
|
||||
},
|
||||
fields:
|
||||
pluginConfig?.searchOverrides?.fields &&
|
||||
typeof pluginConfig?.searchOverrides?.fields === 'function'
|
||||
? pluginConfig?.searchOverrides.fields({ defaultFields })
|
||||
: defaultFields,
|
||||
hooks: {
|
||||
...(pluginConfig?.searchOverrides?.hooks || {}),
|
||||
},
|
||||
labels: {
|
||||
plural: 'Search Results',
|
||||
singular: 'Search Result',
|
||||
},
|
||||
}
|
||||
|
||||
return newConfig
|
||||
}
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import type { CollectionAfterChangeHook, CollectionConfig, Payload, PayloadRequest } from 'payload'
|
||||
import type {
|
||||
CollectionAfterChangeHook,
|
||||
CollectionConfig,
|
||||
Field,
|
||||
Payload,
|
||||
PayloadRequest,
|
||||
} from 'payload'
|
||||
|
||||
export type DocToSync = {
|
||||
[key: string]: any
|
||||
@@ -18,6 +24,8 @@ export type BeforeSync = (args: {
|
||||
searchDoc: DocToSync
|
||||
}) => DocToSync | Promise<DocToSync>
|
||||
|
||||
export type FieldsOverride = (args: { defaultFields: Field[] }) => Field[]
|
||||
|
||||
export type SearchPluginConfig = {
|
||||
beforeSync?: BeforeSync
|
||||
collections?: string[]
|
||||
@@ -25,15 +33,15 @@ export type SearchPluginConfig = {
|
||||
[collection: string]: ((doc: any) => Promise<number> | number) | number
|
||||
}
|
||||
deleteDrafts?: boolean
|
||||
searchOverrides?: Partial<CollectionConfig>
|
||||
searchOverrides?: { fields?: FieldsOverride } & Partial<Omit<CollectionConfig, 'fields'>>
|
||||
syncDrafts?: boolean
|
||||
}
|
||||
|
||||
// Extend the `CollectionAfterChangeHook` with more function args
|
||||
// Convert the `collection` arg from `SanitizedCollectionConfig` to a string
|
||||
export type SyncWithSearch = (
|
||||
Args: Omit<Parameters<CollectionAfterChangeHook>[0], 'collection'> & {
|
||||
Args: {
|
||||
collection: string
|
||||
pluginConfig: SearchPluginConfig
|
||||
},
|
||||
} & Omit<Parameters<CollectionAfterChangeHook>[0], 'collection'>,
|
||||
) => ReturnType<CollectionAfterChangeHook>
|
||||
|
||||
@@ -41,14 +41,14 @@ export default buildConfigWithDefaults({
|
||||
posts: ({ title }) => (title === 'Hello, world!' ? 30 : 20),
|
||||
},
|
||||
searchOverrides: {
|
||||
fields: [
|
||||
fields: ({ defaultFields }) => [
|
||||
...defaultFields,
|
||||
{
|
||||
name: 'excerpt',
|
||||
type: 'text',
|
||||
type: 'textarea',
|
||||
admin: {
|
||||
readOnly: true,
|
||||
position: 'sidebar',
|
||||
},
|
||||
label: 'Excerpt',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user