fix(ui): relationship using list drawer correctly updates when hasMany is true (#12176)
### What? This fixes an issue raised by @maximseshuk in this PR #11553. Here is the text of the original comment: If the field has the property hasMany: true and you select one item, it shows up in the select field, but any additional selected items won't be visible in the select field, even though the data is actually there and can be saved. After refreshing the page, they appear. In addition I added a fix to an issue where the filterOptions weren't being passed in to the useListDrawer hook properly in polymorphic relationships ### How? Instead of using the push method to update the value state, a new array is created and directly set using useState. I think the issue was because using push mutates the original array.
This commit is contained in:
@@ -136,18 +136,38 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
|
||||
let newFilterOptions = filterOptions
|
||||
|
||||
if (value) {
|
||||
;(Array.isArray(value) ? value : [value]).forEach((val) => {
|
||||
;(Array.isArray(relationTo) ? relationTo : [relationTo]).forEach((relationTo) => {
|
||||
const valuesByRelation = (Array.isArray(value) ? value : [value]).reduce((acc, val) => {
|
||||
if (typeof val === 'object' && val.relationTo) {
|
||||
if (!acc[val.relationTo]) {
|
||||
acc[val.relationTo] = []
|
||||
}
|
||||
acc[val.relationTo].push(val.value)
|
||||
} else if (val) {
|
||||
const relation = Array.isArray(relationTo) ? undefined : relationTo
|
||||
if (relation) {
|
||||
if (!acc[relation]) {
|
||||
acc[relation] = []
|
||||
}
|
||||
acc[relation].push(val)
|
||||
}
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
;(Array.isArray(relationTo) ? relationTo : [relationTo]).forEach((relation) => {
|
||||
newFilterOptions = {
|
||||
...(filterOptions || {}),
|
||||
[relationTo]: {
|
||||
...(typeof filterOptions?.[relationTo] === 'object' ? filterOptions[relationTo] : {}),
|
||||
...(newFilterOptions || {}),
|
||||
[relation]: {
|
||||
...(typeof filterOptions?.[relation] === 'object' ? filterOptions[relation] : {}),
|
||||
...(valuesByRelation[relation]
|
||||
? {
|
||||
id: {
|
||||
not_in: [typeof val === 'object' ? val.value : val],
|
||||
},
|
||||
not_in: valuesByRelation[relation],
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -174,8 +194,7 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
|
||||
|
||||
if (hasMany) {
|
||||
const withSelection = Array.isArray(value) ? value : []
|
||||
withSelection.push(formattedSelection)
|
||||
setValue(withSelection)
|
||||
setValue([...withSelection, formattedSelection])
|
||||
} else {
|
||||
setValue(formattedSelection)
|
||||
}
|
||||
|
||||
@@ -742,7 +742,15 @@ describe('relationship', () => {
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
|
||||
const selectedValue = relationshipField.locator('.relationship--multi-value-label__text')
|
||||
await expect(selectedValue).toBeVisible()
|
||||
await expect(selectedValue).toHaveCount(1)
|
||||
|
||||
await relationshipField.click()
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
await button.click()
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
|
||||
const selectedValues = relationshipField.locator('.relationship--multi-value-label__text')
|
||||
await expect(selectedValues).toHaveCount(2)
|
||||
})
|
||||
|
||||
test('should handle `hasMany` polymorphic relationship when `appearance: "drawer"`', async () => {
|
||||
@@ -807,6 +815,42 @@ describe('relationship', () => {
|
||||
await expect(newRows).toHaveCount(1)
|
||||
await expect(listDrawerContent.getByText('Seeded text document')).toHaveCount(0)
|
||||
})
|
||||
|
||||
test('should filter out existing values from polymorphic relationship list drawer', async () => {
|
||||
await page.goto(url.create)
|
||||
const relationshipField = page.locator('#field-polymorphicRelationshipDrawer')
|
||||
await relationshipField.click()
|
||||
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
|
||||
const relationToSelector = page.locator('.list-header__select-collection')
|
||||
await expect(relationToSelector).toBeVisible()
|
||||
|
||||
await relationToSelector.locator('.rs__control').click()
|
||||
const option = relationToSelector.locator('.rs__option').nth(1)
|
||||
await option.click()
|
||||
const rows = listDrawerContent.locator('table tbody tr')
|
||||
await expect(rows).toHaveCount(2)
|
||||
const firstRow = rows.first()
|
||||
const button = firstRow.locator('button')
|
||||
await button.click()
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
|
||||
const selectedValue = relationshipField.locator('.relationship--single-value__text')
|
||||
await expect(selectedValue).toBeVisible()
|
||||
|
||||
await relationshipField.click()
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
await expect(relationToSelector).toBeVisible()
|
||||
await relationToSelector.locator('.rs__control').click()
|
||||
await option.click()
|
||||
const newRows = listDrawerContent.locator('table tbody tr')
|
||||
await expect(newRows).toHaveCount(1)
|
||||
const newFirstRow = newRows.first()
|
||||
const newButton = newFirstRow.locator('button')
|
||||
await newButton.click()
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
})
|
||||
})
|
||||
|
||||
async function createTextFieldDoc(overrides?: Partial<TextField>): Promise<TextField> {
|
||||
|
||||
@@ -158,7 +158,7 @@ const RelationshipFields: CollectionConfig = {
|
||||
},
|
||||
{
|
||||
name: 'relationshipDrawerHasManyPolymorphic',
|
||||
relationTo: ['text-fields'],
|
||||
relationTo: ['text-fields', 'array-fields'],
|
||||
admin: {
|
||||
appearance: 'drawer',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user