Skip to content

Commit

Permalink
fix: enable relationship & upload field population in versions (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
PatrikKozak authored Aug 6, 2024
1 parent 1a0ef48 commit 9865ae9
Show file tree
Hide file tree
Showing 10 changed files with 353 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,46 +25,72 @@ const generateLabelFromValue = (
locale: string,
value: { relationTo: string; value: RelationshipValue } | RelationshipValue,
): string => {
let relation: string
if (Array.isArray(value)) {
return value
.map((v) => generateLabelFromValue(collections, field, locale, v))
.filter(Boolean) // Filters out any undefined or empty values
.join(', ')
}

let relatedDoc: RelationshipValue
let valueToReturn = '' as any

if (value === null || typeof value === 'undefined') {
return String(value)
}

if (Array.isArray(field.relationTo)) {
if (typeof value === 'object') {
relation = value.relationTo
relatedDoc = value.value
}
const relationTo = 'relationTo' in field ? field.relationTo : undefined

if (value === null || typeof value === 'undefined') {
return String(value)
}

if (typeof value === 'object' && 'relationTo' in value) {
relatedDoc = value.value
} else {
relation = field.relationTo
// Non-polymorphic relationship
relatedDoc = value
}

const relatedCollection = collections.find((c) => c.slug === relation)
const relatedCollection = relationTo
? collections.find(
(c) =>
c.slug ===
(typeof value === 'object' && 'relationTo' in value ? value.relationTo : relationTo),
)
: null

if (relatedCollection) {
const useAsTitle = relatedCollection?.admin?.useAsTitle

// eslint-disable-next-line react-hooks/rules-of-hooks
const useAsTitleField = useUseTitleField(relatedCollection)

let titleFieldIsLocalized = false

if (useAsTitleField && fieldAffectsData(useAsTitleField))
if (useAsTitleField && fieldAffectsData(useAsTitleField)) {
titleFieldIsLocalized = useAsTitleField.localized
}

if (typeof relatedDoc?.[useAsTitle] !== 'undefined') {
valueToReturn = relatedDoc[useAsTitle]
} else if (typeof relatedDoc?.id !== 'undefined') {
valueToReturn = relatedDoc.id
} else {
valueToReturn = relatedDoc
}

if (typeof valueToReturn === 'object' && titleFieldIsLocalized) {
valueToReturn = valueToReturn[locale]
}
} else if (relatedDoc) {
// Handle non-polymorphic `hasMany` relationships or fallback
if (typeof relatedDoc.id !== 'undefined') {
valueToReturn = relatedDoc.id
} else {
valueToReturn = relatedDoc
}
}

if (typeof valueToReturn === 'object' && valueToReturn !== null) {
valueToReturn = JSON.stringify(valueToReturn)
}

return valueToReturn
Expand All @@ -79,25 +105,31 @@ const Relationship: React.FC<Props & { field: RelationshipField }> = ({
const { i18n, t } = useTranslation('general')
const { code: locale } = useLocale()

let placeholder = ''
const placeholder = `[${t('noValue')}]`

if (version === comparison) placeholder = `[${t('noValue')}]`
let versionToRender: string | undefined = placeholder
let comparisonToRender: string | undefined = placeholder

let versionToRender = version
let comparisonToRender = comparison
if (version) {
if ('hasMany' in field && field.hasMany && Array.isArray(version)) {
versionToRender =
version.map((val) => generateLabelFromValue(collections, field, locale, val)).join(', ') ||
placeholder
} else {
versionToRender = generateLabelFromValue(collections, field, locale, version) || placeholder
}
}

if (field.hasMany) {
if (Array.isArray(version))
versionToRender = version
.map((val) => generateLabelFromValue(collections, field, locale, val))
.join(', ')
if (Array.isArray(comparison))
comparisonToRender = comparison
.map((val) => generateLabelFromValue(collections, field, locale, val))
.join(', ')
} else {
versionToRender = generateLabelFromValue(collections, field, locale, version)
comparisonToRender = generateLabelFromValue(collections, field, locale, comparison)
if (comparison) {
if ('hasMany' in field && field.hasMany && Array.isArray(comparison)) {
comparisonToRender =
comparison
.map((val) => generateLabelFromValue(collections, field, locale, val))
.join(', ') || placeholder
} else {
comparisonToRender =
generateLabelFromValue(collections, field, locale, comparison) || placeholder
}
}

return (
Expand Down
22 changes: 13 additions & 9 deletions packages/payload/src/admin/components/views/Version/Version.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ const VersionView: React.FC<Props> = ({ collection, global }) => {
initialParams: { depth: 1, draft: 'true', locale: '*' },
})

const hasDraftsEnabled = collection?.versions?.drafts || global?.versions?.drafts

const sharedParams = (status) => {
return {
depth: 0,
Expand All @@ -122,24 +124,26 @@ const VersionView: React.FC<Props> = ({ collection, global }) => {
}

const [{ data: draft }] = usePayloadAPI(compareBaseURL, {
initialParams: { ...sharedParams('draft') },
initialParams: hasDraftsEnabled ? { ...sharedParams('draft') } : {},
})

const [{ data: published }] = usePayloadAPI(compareBaseURL, {
initialParams: { ...sharedParams('published') },
initialParams: hasDraftsEnabled ? { ...sharedParams('published') } : {},
})

useEffect(() => {
const formattedPublished = published?.docs?.length > 0 && published?.docs[0]
const formattedDraft = draft?.docs?.length > 0 && draft?.docs[0]
if (hasDraftsEnabled) {
const formattedPublished = published?.docs?.length > 0 && published?.docs[0]
const formattedDraft = draft?.docs?.length > 0 && draft?.docs[0]

if (!formattedPublished || !formattedDraft) return
if (!formattedPublished || !formattedDraft) return

const publishedNewerThanDraft = formattedPublished?.updatedAt > formattedDraft?.updatedAt
const publishedNewerThanDraft = formattedPublished?.updatedAt > formattedDraft?.updatedAt

setLatestDraftVersion(publishedNewerThanDraft ? undefined : formattedDraft?.id)
setLatestPublishedVersion(formattedPublished.latest ? formattedPublished?.id : undefined)
}, [draft, published])
setLatestDraftVersion(publishedNewerThanDraft ? undefined : formattedDraft?.id)
setLatestPublishedVersion(formattedPublished.latest ? formattedPublished?.id : undefined)
}
}, [hasDraftsEnabled, draft, published])

useEffect(() => {
let nav: StepNavItem[] = []
Expand Down
90 changes: 51 additions & 39 deletions packages/payload/src/admin/components/views/Versions/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,45 +47,57 @@ export const buildVersionColumns = (
t: TFunction,
latestDraftVersion?: string,
latestPublishedVersion?: string,
): Column[] => [
{
name: '',
accessor: 'updatedAt',
active: true,
components: {
Heading: <SortColumn label={t('general:updatedAt')} name="updatedAt" />,
renderCell: (row, data) => (
<CreatedAtCell collection={collection} date={data} global={global} id={row?.id} />
),
},
label: '',
},
{
name: '',
accessor: 'id',
active: true,
components: {
Heading: <SortColumn disable label={t('versionID')} name="id" />,
renderCell: (row, data) => <TextCell>{data}</TextCell>,
): Column[] => {
const entityConfig = collection || global

const columns: Column[] = [
{
name: '',
accessor: 'updatedAt',
active: true,
components: {
Heading: <SortColumn label={t('general:updatedAt')} name="updatedAt" />,
renderCell: (row, data) => (
<CreatedAtCell collection={collection} date={data} global={global} id={row?.id} />
),
},
label: '',
},
label: '',
},
{
name: '',
accessor: 'autosave',
active: true,
components: {
Heading: <SortColumn disable label={t('status')} name="autosave" />,
renderCell: (row) => {
return (
<AutosaveCell
latestDraftVersion={latestDraftVersion}
latestPublishedVersion={latestPublishedVersion}
rowData={row}
/>
)
{
name: '',
accessor: 'id',
active: true,
components: {
Heading: <SortColumn disable label={t('versionID')} name="id" />,
renderCell: (row, data) => <TextCell>{data}</TextCell>,
},
label: '',
},
label: '',
},
]
]

if (
entityConfig?.versions?.drafts ||
(entityConfig?.versions?.drafts && entityConfig.versions.drafts?.autosave)
) {
columns.push({
name: '',
accessor: 'autosave',
active: true,
components: {
Heading: <SortColumn disable label={t('status')} name="autosave" />,
renderCell: (row) => {
return (
<AutosaveCell
latestDraftVersion={latestDraftVersion}
latestPublishedVersion={latestPublishedVersion}
rowData={row}
/>
)
},
},
label: '',
})
}

return columns
}
22 changes: 13 additions & 9 deletions packages/payload/src/admin/components/views/Versions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ const VersionsView: React.FC<IndexProps> = (props) => {
const [{ data: versionsData, isLoading: isLoadingVersions }, { setParams }] =
usePayloadAPI(fetchURL)

const hasDraftsEnabled = collection?.versions?.drafts || global?.versions?.drafts

const sharedParams = (status) => {
return {
depth: 0,
Expand All @@ -108,23 +110,25 @@ const VersionsView: React.FC<IndexProps> = (props) => {
}

const [{ data: draft }] = usePayloadAPI(fetchURL, {
initialParams: { ...sharedParams('draft') },
initialParams: hasDraftsEnabled ? { ...sharedParams('draft') } : {},
})

const [{ data: published }] = usePayloadAPI(fetchURL, {
initialParams: { ...sharedParams('published') },
initialParams: hasDraftsEnabled ? { ...sharedParams('published') } : {},
})

useEffect(() => {
const formattedPublished = published?.docs?.length > 0 && published?.docs[0]
const formattedDraft = draft?.docs?.length > 0 && draft?.docs[0]
if (hasDraftsEnabled) {
const formattedPublished = published?.docs?.length > 0 && published?.docs[0]
const formattedDraft = draft?.docs?.length > 0 && draft?.docs[0]

if (!formattedPublished || !formattedDraft) return
if (!formattedPublished || !formattedDraft) return

const publishedNewerThanDraft = formattedPublished?.updatedAt > formattedDraft?.updatedAt
setLatestDraftVersion(publishedNewerThanDraft ? undefined : formattedDraft?.id)
setLatestPublishedVersion(formattedPublished.latest ? formattedPublished?.id : undefined)
}, [draft, published])
const publishedNewerThanDraft = formattedPublished?.updatedAt > formattedDraft?.updatedAt
setLatestDraftVersion(publishedNewerThanDraft ? undefined : formattedDraft?.id)
setLatestPublishedVersion(formattedPublished.latest ? formattedPublished?.id : undefined)
}
}, [hasDraftsEnabled, draft, published])

useEffect(() => {
const params = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,25 @@ const relationshipPopulationPromise = async ({

if (fieldSupportsMany(field) && field.hasMany) {
if (
field.localized &&
locale === 'all' &&
typeof siblingDoc[field.name] === 'object' &&
siblingDoc[field.name] !== null
) {
Object.keys(siblingDoc[field.name]).forEach((key) => {
if (Array.isArray(siblingDoc[field.name][key])) {
siblingDoc[field.name][key].forEach((relatedDoc, index) => {
Object.keys(siblingDoc[field.name]).forEach((localeKey) => {
if (Array.isArray(siblingDoc[field.name][localeKey])) {
siblingDoc[field.name][localeKey].forEach((relatedDoc, index) => {
const rowPromise = async () => {
await populate({
currentDepth,
data: siblingDoc[field.name][key][index],
data: siblingDoc[field.name][localeKey][index],
dataReference: resultingDoc,
depth: populateDepth,
draft,
fallbackLocale,
field,
index,
key,
key: localeKey,
locale,
overrideAccess,
req,
Expand Down Expand Up @@ -178,21 +179,22 @@ const relationshipPopulationPromise = async ({
})
}
} else if (
field.localized &&
locale === 'all' &&
typeof siblingDoc[field.name] === 'object' &&
siblingDoc[field.name] !== null &&
locale === 'all'
siblingDoc[field.name] !== null
) {
Object.keys(siblingDoc[field.name]).forEach((key) => {
Object.keys(siblingDoc[field.name]).forEach((localeKey) => {
const rowPromise = async () => {
await populate({
currentDepth,
data: siblingDoc[field.name][key],
data: siblingDoc[field.name][localeKey],
dataReference: resultingDoc,
depth: populateDepth,
draft,
fallbackLocale,
field,
key,
key: localeKey,
locale,
overrideAccess,
req,
Expand Down
1 change: 1 addition & 0 deletions test/fields-relationship/collectionSlugs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export const relationWithTitleSlug = 'relation-with-title'
export const relationUpdatedExternallySlug = 'relation-updated-externally'
export const collection1Slug = 'collection-1'
export const collection2Slug = 'collection-2'
export const versionedRelationshipFieldSlug = 'versioned-relationship-field'
Loading

0 comments on commit 9865ae9

Please sign in to comment.