Files
payload/packages/next/src/views/Version/RenderFieldsToDiff/index.tsx

157 lines
4.7 KiB
TypeScript

'use client'
import type { DiffMethod } from 'react-diff-viewer-continued'
import { fieldAffectsData, fieldIsID } from 'payload/shared'
import React from 'react'
import type { diffComponents as _diffComponents } from './fields/index.js'
import type { FieldDiffProps, Props } from './types.js'
import { diffMethods } from './fields/diffMethods.js'
import Nested from './fields/Nested/index.js'
import './index.scss'
const baseClass = 'render-field-diffs'
const RenderFieldsToDiff: React.FC<Props> = ({
comparison,
diffComponents: __diffComponents,
fieldPermissions,
fields,
i18n,
locales,
version,
}) => {
// typing it as `as typeof _diffComponents` here ensures the TField generics of DiffComponentProps are respected.
// Without it, you could pass a UI field to the Tabs component, without it erroring
const diffComponents: typeof _diffComponents = __diffComponents as typeof _diffComponents
return (
<div className={baseClass}>
{fields?.map((field, i) => {
if (fieldIsID(field)) {
return null
}
const Component = diffComponents[field.type]
const isRichText = field.type === 'richText'
const diffMethod: DiffMethod = diffMethods[field.type] || 'CHARS'
if (Component) {
if (fieldAffectsData(field)) {
const fieldName = field.name
const valueIsObject = field.type === 'code' || field.type === 'json'
const versionValue = valueIsObject
? JSON.stringify(version?.[fieldName])
: version?.[fieldName]
const comparisonValue = valueIsObject
? JSON.stringify(comparison?.[fieldName])
: comparison?.[fieldName]
const hasPermission =
fieldPermissions === true ||
fieldPermissions?.[fieldName] === true ||
fieldPermissions?.[fieldName]?.read
const subFieldPermissions =
fieldPermissions === true ||
fieldPermissions?.[fieldName] === true ||
fieldPermissions?.[fieldName]?.fields
if (!hasPermission) {
return null
}
const baseCellProps: FieldDiffProps = {
comparison: comparisonValue,
diffComponents,
diffMethod,
field,
fieldPermissions: subFieldPermissions,
fields: 'fields' in field ? field?.fields : fields,
i18n,
isRichText,
locales,
version: versionValue,
}
if (field.localized) {
return (
<div className={`${baseClass}__field`} key={i}>
{locales.map((locale, index) => {
const versionLocaleValue = versionValue?.[locale]
const comparisonLocaleValue = comparisonValue?.[locale]
const cellProps = {
...baseCellProps,
comparison: comparisonLocaleValue,
version: versionLocaleValue,
}
return (
<div className={`${baseClass}__locale`} key={[locale, index].join('-')}>
<div className={`${baseClass}__locale-value`}>
<Component {...cellProps} locale={locale} />
</div>
</div>
)
})}
</div>
)
}
return (
<div className={`${baseClass}__field`} key={i}>
<Component {...baseCellProps} />
</div>
)
}
if (field.type === 'tabs' && 'tabs' in field) {
const Tabs = diffComponents.tabs
return (
<Tabs
comparison={comparison}
diffComponents={diffComponents}
field={field}
fieldPermissions={fieldPermissions}
fields={[]}
i18n={i18n}
key={i}
locales={locales}
version={version}
/>
)
}
// At this point, we are dealing with a `row`, etc
if ('fields' in field) {
return (
<Nested
comparison={comparison}
diffComponents={diffComponents}
disableGutter
field={field}
fieldPermissions={fieldPermissions}
fields={field.fields}
i18n={i18n}
key={i}
locales={locales}
version={version}
/>
)
}
}
return null
})}
</div>
)
}
export default RenderFieldsToDiff