157 lines
4.7 KiB
TypeScript
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
|