### What? Presentational Fields such as [Row](https://payloadcms.com/docs/fields/row) are described as only effecting the admin panel. If they do not impact data, their types should not include hooks in the fields config. ### Why? Developers can currently assign hooks to these fields, expecting them to work, when in reality they are not called. ### How? Omit `hooks` from `FieldBase` Fixes #11507 --------- Co-authored-by: German Jablonski <43938777+GermanJablo@users.noreply.github.com>
162 lines
4.0 KiB
TypeScript
162 lines
4.0 KiB
TypeScript
import type { CollectionConfig, Field, GroupField, TextField } from 'payload'
|
|
|
|
import path from 'path'
|
|
|
|
import type { GeneratedAdapter, GenerateFileURL } from '../types.js'
|
|
|
|
import { getAfterReadHook } from '../hooks/afterRead.js'
|
|
|
|
interface Args {
|
|
adapter: GeneratedAdapter
|
|
collection: CollectionConfig
|
|
disablePayloadAccessControl?: true
|
|
generateFileURL?: GenerateFileURL
|
|
prefix?: string
|
|
}
|
|
|
|
export const getFields = ({
|
|
adapter,
|
|
collection,
|
|
disablePayloadAccessControl,
|
|
generateFileURL,
|
|
prefix,
|
|
}: Args): Field[] => {
|
|
const baseURLField: TextField = {
|
|
name: 'url',
|
|
type: 'text',
|
|
admin: {
|
|
hidden: true,
|
|
readOnly: true,
|
|
},
|
|
label: 'URL',
|
|
}
|
|
|
|
const basePrefixField: TextField = {
|
|
name: 'prefix',
|
|
type: 'text',
|
|
admin: {
|
|
hidden: true,
|
|
readOnly: true,
|
|
},
|
|
}
|
|
|
|
const fields = [...collection.fields, ...(adapter.fields || [])]
|
|
|
|
// Inject a hook into all URL fields to generate URLs
|
|
|
|
let existingURLFieldIndex = -1
|
|
|
|
const existingURLField = fields.find((existingField, i) => {
|
|
if ('name' in existingField && existingField.name === 'url') {
|
|
existingURLFieldIndex = i
|
|
return true
|
|
}
|
|
return false
|
|
}) as TextField
|
|
|
|
if (existingURLFieldIndex > -1) {
|
|
fields.splice(existingURLFieldIndex, 1)
|
|
}
|
|
|
|
fields.push({
|
|
...baseURLField,
|
|
...(existingURLField || {}),
|
|
hooks: {
|
|
afterRead: [
|
|
getAfterReadHook({ adapter, collection, disablePayloadAccessControl, generateFileURL }),
|
|
...(existingURLField?.hooks?.afterRead || []),
|
|
],
|
|
},
|
|
} as TextField)
|
|
|
|
if (typeof collection.upload === 'object' && collection.upload.imageSizes) {
|
|
let existingSizesFieldIndex = -1
|
|
|
|
const existingSizesField = fields.find((existingField, i) => {
|
|
if ('name' in existingField && existingField.name === 'sizes') {
|
|
existingSizesFieldIndex = i
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}) as GroupField
|
|
|
|
if (existingSizesFieldIndex > -1) {
|
|
fields.splice(existingSizesFieldIndex, 1)
|
|
}
|
|
|
|
const sizesField: Field = {
|
|
...(existingSizesField || {}),
|
|
name: 'sizes',
|
|
type: 'group',
|
|
admin: {
|
|
hidden: true,
|
|
},
|
|
fields: collection.upload.imageSizes.map((size) => {
|
|
const existingSizeField = existingSizesField?.fields.find(
|
|
(existingField) => 'name' in existingField && existingField.name === size.name,
|
|
) as GroupField
|
|
|
|
const existingSizeURLField = existingSizeField?.fields.find(
|
|
(existingField) => 'name' in existingField && existingField.name === 'url',
|
|
) as GroupField
|
|
|
|
return {
|
|
...existingSizeField,
|
|
name: size.name,
|
|
type: 'group',
|
|
fields: [
|
|
...(adapter.fields || []),
|
|
{
|
|
...(existingSizeURLField || {}),
|
|
...baseURLField,
|
|
hooks: {
|
|
afterRead: [
|
|
getAfterReadHook({
|
|
adapter,
|
|
collection,
|
|
disablePayloadAccessControl,
|
|
generateFileURL,
|
|
size,
|
|
}),
|
|
...((typeof existingSizeURLField === 'object' &&
|
|
'hooks' in existingSizeURLField &&
|
|
existingSizeURLField?.hooks?.afterRead) ||
|
|
[]),
|
|
],
|
|
},
|
|
},
|
|
],
|
|
} as Field
|
|
}),
|
|
}
|
|
|
|
fields.push(sizesField)
|
|
}
|
|
|
|
// If prefix is enabled, save it to db
|
|
if (typeof prefix !== 'undefined') {
|
|
let existingPrefixFieldIndex = -1
|
|
|
|
const existingPrefixField = fields.find((existingField, i) => {
|
|
if ('name' in existingField && existingField.name === 'prefix') {
|
|
existingPrefixFieldIndex = i
|
|
return true
|
|
}
|
|
return false
|
|
}) as TextField
|
|
|
|
if (existingPrefixFieldIndex > -1) {
|
|
fields.splice(existingPrefixFieldIndex, 1)
|
|
}
|
|
|
|
fields.push({
|
|
...basePrefixField,
|
|
...(existingPrefixField || {}),
|
|
defaultValue: path.posix.join(prefix),
|
|
} as TextField)
|
|
}
|
|
|
|
return fields
|
|
}
|