Skip to content

Commit a8bec9a

Browse files
authored
fix(ui): only show bulk select all when count is less than total (#11329)
It doesn't make sense to display "select all" when bulk editing if your current selection already contains all records.
1 parent 5d7be15 commit a8bec9a

File tree

4 files changed

+50
-23
lines changed

4 files changed

+50
-23
lines changed

packages/ui/src/elements/ListSelection/index.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@
22

33
@layer payload-default {
44
.list-selection {
5+
display: flex;
56
margin-left: auto;
67
color: var(--theme-elevation-500);
8+
gap: 0.5em;
79

810
&__button {
911
color: var(--theme-elevation-500);
1012
background: unset;
1113
border: none;
1214
text-decoration: underline;
1315
cursor: pointer;
16+
padding: 0;
17+
font-size: inherit;
1418
}
1519

1620
@include small-break {

packages/ui/src/elements/ListSelection/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ export const ListSelection: React.FC<ListSelectionProps> = ({ label }) => {
2222
return (
2323
<div className={baseClass}>
2424
<span>{t('general:selectedCount', { count, label })}</span>
25-
{selectAll !== SelectAllStatus.AllAvailable && (
25+
{selectAll !== SelectAllStatus.AllAvailable && count < totalDocs && (
2626
<Fragment>
27-
{' '}
28-
&mdash;
27+
<span>&mdash;</span>
2928
<button
3029
aria-label={t('general:selectAll', { count, label })}
3130
className={`${baseClass}__button`}
31+
id="select-all-across-pages"
3232
onClick={() => toggleAll(true)}
3333
type="button"
3434
>

test/admin/e2e/general/e2e.spec.ts

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ let payload: PayloadTestSDK<Config>
5151
import { navigateToDoc } from 'helpers/e2e/navigateToDoc.js'
5252
import { openDocControls } from 'helpers/e2e/openDocControls.js'
5353
import path from 'path'
54+
import { wait } from 'payload/shared'
5455
import { fileURLToPath } from 'url'
5556

5657
import type { PayloadTestSDK } from '../../../helpers/sdk/index.js'
@@ -721,25 +722,31 @@ describe('General', () => {
721722
'Deleted 3 Posts successfully.',
722723
)
723724

724-
await expect(page.locator('.collection-list__no-results')).toBeVisible()
725+
// Poll until router has refreshed
726+
await expect.poll(() => page.locator('.collection-list__no-results').isVisible()).toBeTruthy()
725727
})
726728

727729
test('should bulk delete with filters and across pages', async () => {
728730
await deleteAllPosts()
729-
await Promise.all([createPost({ title: 'Post 1' }), createPost({ title: 'Post 2' })])
731+
732+
Array.from({ length: 6 }).forEach(async (_, i) => {
733+
await createPost({ title: `Post ${i + 1}` })
734+
})
735+
730736
await page.goto(postsUrl.list)
731-
await page.locator('#search-filter-input').fill('Post 1')
732-
await expect(page.locator('.table table > tbody > tr')).toHaveCount(1)
737+
await page.locator('#search-filter-input').fill('Post')
738+
await expect(page.locator('.table table > tbody > tr')).toHaveCount(5)
733739
await page.locator('input#select-all').check()
734-
await page.locator('button.list-selection__button').click()
740+
await page.locator('button#select-all-across-pages').click()
735741
await page.locator('.delete-documents__toggle').click()
736742
await page.locator('#delete-posts #confirm-action').click()
737743

738744
await expect(page.locator('.payload-toast-container .toast-success')).toHaveText(
739-
'Deleted 1 Post successfully.',
745+
'Deleted 6 Posts successfully.',
740746
)
741747

742-
await expect(page.locator('.table table > tbody > tr')).toHaveCount(1)
748+
// Poll until router has refreshed
749+
await expect.poll(() => page.locator('.table table > tbody > tr').count()).toBe(0)
743750
})
744751

745752
test('should bulk update', async () => {
@@ -835,17 +842,27 @@ describe('General', () => {
835842
expect(updatedPost.docs[0].defaultValueField).toBe('not the default value')
836843
})
837844

845+
test('should not show "select all across pages" button if already selected all', async () => {
846+
await deleteAllPosts()
847+
await createPost({ title: `Post 1` })
848+
await page.goto(postsUrl.list)
849+
await page.locator('input#select-all').check()
850+
await expect(page.locator('button#select-all-across-pages')).toBeHidden()
851+
})
852+
838853
test('should bulk update with filters and across pages', async () => {
839854
// First, delete all posts created by the seed
840855
await deleteAllPosts()
841-
const post1Title = 'Post 1'
842-
await Promise.all([createPost({ title: post1Title }), createPost({ title: 'Post 2' })])
843-
const updatedPostTitle = `${post1Title} (Updated)`
856+
857+
Array.from({ length: 6 }).forEach(async (_, i) => {
858+
await createPost({ title: `Post ${i + 1}` })
859+
})
860+
844861
await page.goto(postsUrl.list)
845-
await page.locator('#search-filter-input').fill('Post 1')
846-
await expect(page.locator('.table table > tbody > tr')).toHaveCount(1)
862+
await page.locator('#search-filter-input').fill('Post')
863+
await expect(page.locator('.table table > tbody > tr')).toHaveCount(5)
847864
await page.locator('input#select-all').check()
848-
await page.locator('button.list-selection__button').click()
865+
await page.locator('button#select-all-across-pages').click()
849866
await page.locator('.edit-many__toggle').click()
850867
await page.locator('.field-select .rs__control').click()
851868

@@ -857,23 +874,29 @@ describe('General', () => {
857874
await titleOption.click()
858875
const titleInput = page.locator('#field-title')
859876
await expect(titleInput).toBeVisible()
860-
await titleInput.fill(updatedPostTitle)
877+
const updatedTitle = `Post (Updated)`
878+
await titleInput.fill(updatedTitle)
861879

862880
await page.locator('.form-submit button[type="submit"].edit-many__publish').click()
863881
await expect(page.locator('.payload-toast-container .toast-success')).toContainText(
864-
'Updated 1 Post successfully.',
882+
'Updated 6 Posts successfully.',
865883
)
866884

867-
await expect(page.locator('.table table > tbody > tr')).toHaveCount(1)
868-
await expect(page.locator('.row-1 .cell-title')).toContainText(updatedPostTitle)
885+
// Poll until router has refreshed
886+
await expect.poll(() => page.locator('.table table > tbody > tr').count()).toBe(5)
887+
await expect(page.locator('.row-1 .cell-title')).toContainText(updatedTitle)
869888
})
870889

871890
test('should update selection state after deselecting item following select all', async () => {
872891
await deleteAllPosts()
873-
await createPost({ title: 'Post 1' })
892+
893+
Array.from({ length: 6 }).forEach(async (_, i) => {
894+
await createPost({ title: `Post ${i + 1}` })
895+
})
896+
874897
await page.goto(postsUrl.list)
875898
await page.locator('input#select-all').check()
876-
await page.locator('button.list-selection__button').click()
899+
await page.locator('button#select-all-across-pages').click()
877900

878901
// Deselect the first row
879902
await page.locator('.row-1 input').click()

tsconfig.base.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
}
3232
],
3333
"paths": {
34-
"@payload-config": ["./test/versions/config.ts"],
34+
"@payload-config": ["./test/admin/config.ts"],
3535
"@payloadcms/live-preview": ["./packages/live-preview/src"],
3636
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],
3737
"@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],

0 commit comments

Comments
 (0)