chore: passes allowCreate into list drawer and adds test (#11284)
### What? We had an `allowCreate` prop for the list drawer that doesn't do anything. This PR passes the prop through so it can be used. ### How? Passes `allowCreate` down to the list view and ties it with `hasCreatePermission` #### Testing - Use `admin` test suite and `withListDrawer` collection. - Test added to the `admin/e2e/list-view`. Fixes #11246
This commit is contained in:
committed by
GitHub
parent
26163a7535
commit
c05f10abbc
@@ -87,6 +87,7 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
|||||||
const { List: ViewResult } = (await serverFunction({
|
const { List: ViewResult } = (await serverFunction({
|
||||||
name: 'render-list',
|
name: 'render-list',
|
||||||
args: {
|
args: {
|
||||||
|
allowCreate,
|
||||||
collectionSlug: slug,
|
collectionSlug: slug,
|
||||||
disableBulkDelete: true,
|
disableBulkDelete: true,
|
||||||
disableBulkEdit: true,
|
disableBulkEdit: true,
|
||||||
@@ -160,6 +161,7 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ListDrawerContextProvider
|
<ListDrawerContextProvider
|
||||||
|
allowCreate={allowCreate}
|
||||||
createNewDrawerSlug={documentDrawerSlug}
|
createNewDrawerSlug={documentDrawerSlug}
|
||||||
DocumentDrawerToggler={DocumentDrawerToggler}
|
DocumentDrawerToggler={DocumentDrawerToggler}
|
||||||
drawerSlug={drawerSlug}
|
drawerSlug={drawerSlug}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import type { UseDocumentDrawer } from '../DocumentDrawer/types.js'
|
|||||||
import type { Option } from '../ReactSelect/index.js'
|
import type { Option } from '../ReactSelect/index.js'
|
||||||
|
|
||||||
export type ListDrawerContextProps = {
|
export type ListDrawerContextProps = {
|
||||||
|
readonly allowCreate?: boolean
|
||||||
readonly createNewDrawerSlug?: string
|
readonly createNewDrawerSlug?: string
|
||||||
readonly DocumentDrawerToggler?: ReturnType<UseDocumentDrawer>[1]
|
readonly DocumentDrawerToggler?: ReturnType<UseDocumentDrawer>[1]
|
||||||
readonly drawerSlug?: string
|
readonly drawerSlug?: string
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export function DefaultListView(props: ListViewClientProps) {
|
|||||||
disableBulkDelete,
|
disableBulkDelete,
|
||||||
disableBulkEdit,
|
disableBulkEdit,
|
||||||
enableRowSelections,
|
enableRowSelections,
|
||||||
hasCreatePermission,
|
hasCreatePermission: hasCreatePermissionFromProps,
|
||||||
listMenuItems,
|
listMenuItems,
|
||||||
listPreferences,
|
listPreferences,
|
||||||
newDocumentURL,
|
newDocumentURL,
|
||||||
@@ -63,7 +63,17 @@ export function DefaultListView(props: ListViewClientProps) {
|
|||||||
|
|
||||||
const [Table, setTable] = useState(InitialTable)
|
const [Table, setTable] = useState(InitialTable)
|
||||||
|
|
||||||
const { createNewDrawerSlug, drawerSlug: listDrawerSlug, onBulkSelect } = useListDrawerContext()
|
const {
|
||||||
|
allowCreate,
|
||||||
|
createNewDrawerSlug,
|
||||||
|
drawerSlug: listDrawerSlug,
|
||||||
|
onBulkSelect,
|
||||||
|
} = useListDrawerContext()
|
||||||
|
|
||||||
|
const hasCreatePermission =
|
||||||
|
allowCreate !== undefined
|
||||||
|
? allowCreate && hasCreatePermissionFromProps
|
||||||
|
: hasCreatePermissionFromProps
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (InitialTable) {
|
if (InitialTable) {
|
||||||
@@ -145,7 +155,6 @@ export function DefaultListView(props: ListViewClientProps) {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
}, [setStepNav, labels, drawerDepth])
|
}, [setStepNav, labels, drawerDepth])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<TableColumnsProvider
|
<TableColumnsProvider
|
||||||
|
|||||||
30
test/admin/collections/ListDrawer.ts
Normal file
30
test/admin/collections/ListDrawer.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
|
import { listDrawerSlug } from '../slugs.js'
|
||||||
|
|
||||||
|
export const ListDrawer: CollectionConfig = {
|
||||||
|
slug: listDrawerSlug,
|
||||||
|
admin: {
|
||||||
|
components: {
|
||||||
|
beforeListTable: [
|
||||||
|
{
|
||||||
|
path: '/components/BeforeList/index.js#SelectPostsButton',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'number',
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
23
test/admin/components/BeforeList/index.tsx
Normal file
23
test/admin/components/BeforeList/index.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// src/components/SelectPostsButton.tsx
|
||||||
|
'use client'
|
||||||
|
import { Button, type UseListDrawer, useListDrawer } from '@payloadcms/ui'
|
||||||
|
import { useMemo } from 'react'
|
||||||
|
|
||||||
|
type UseListDrawerArgs = Parameters<UseListDrawer>[0]
|
||||||
|
|
||||||
|
export const SelectPostsButton = () => {
|
||||||
|
const listDrawerArgs = useMemo<UseListDrawerArgs>(
|
||||||
|
() => ({
|
||||||
|
collectionSlugs: ['with-list-drawer'],
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
const [ListDrawer, _, { toggleDrawer }] = useListDrawer(listDrawerArgs)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button onClick={() => toggleDrawer()}>Select posts</Button>
|
||||||
|
<ListDrawer allowCreate={false} enableRowSelections={false} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import { CollectionGroup1B } from './collections/Group1B.js'
|
|||||||
import { CollectionGroup2A } from './collections/Group2A.js'
|
import { CollectionGroup2A } from './collections/Group2A.js'
|
||||||
import { CollectionGroup2B } from './collections/Group2B.js'
|
import { CollectionGroup2B } from './collections/Group2B.js'
|
||||||
import { CollectionHidden } from './collections/Hidden.js'
|
import { CollectionHidden } from './collections/Hidden.js'
|
||||||
|
import { ListDrawer } from './collections/ListDrawer.js'
|
||||||
import { CollectionNoApiView } from './collections/NoApiView.js'
|
import { CollectionNoApiView } from './collections/NoApiView.js'
|
||||||
import { CollectionNotInView } from './collections/NotInView.js'
|
import { CollectionNotInView } from './collections/NotInView.js'
|
||||||
import { Posts } from './collections/Posts.js'
|
import { Posts } from './collections/Posts.js'
|
||||||
@@ -39,7 +40,6 @@ import {
|
|||||||
protectedCustomNestedViewPath,
|
protectedCustomNestedViewPath,
|
||||||
publicCustomViewPath,
|
publicCustomViewPath,
|
||||||
} from './shared.js'
|
} from './shared.js'
|
||||||
|
|
||||||
export default buildConfigWithDefaults({
|
export default buildConfigWithDefaults({
|
||||||
admin: {
|
admin: {
|
||||||
importMap: {
|
importMap: {
|
||||||
@@ -157,6 +157,7 @@ export default buildConfigWithDefaults({
|
|||||||
DisableDuplicate,
|
DisableDuplicate,
|
||||||
BaseListFilter,
|
BaseListFilter,
|
||||||
with300Documents,
|
with300Documents,
|
||||||
|
ListDrawer,
|
||||||
],
|
],
|
||||||
globals: [
|
globals: [
|
||||||
GlobalHidden,
|
GlobalHidden,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { customAdminRoutes } from '../../shared.js'
|
|||||||
import {
|
import {
|
||||||
customViews1CollectionSlug,
|
customViews1CollectionSlug,
|
||||||
geoCollectionSlug,
|
geoCollectionSlug,
|
||||||
|
listDrawerSlug,
|
||||||
postsCollectionSlug,
|
postsCollectionSlug,
|
||||||
with300DocumentsSlug,
|
with300DocumentsSlug,
|
||||||
} from '../../slugs.js'
|
} from '../../slugs.js'
|
||||||
@@ -56,6 +57,7 @@ describe('List View', () => {
|
|||||||
let baseListFiltersUrl: AdminUrlUtil
|
let baseListFiltersUrl: AdminUrlUtil
|
||||||
let customViewsUrl: AdminUrlUtil
|
let customViewsUrl: AdminUrlUtil
|
||||||
let with300DocumentsUrl: AdminUrlUtil
|
let with300DocumentsUrl: AdminUrlUtil
|
||||||
|
let withListViewUrl: AdminUrlUtil
|
||||||
|
|
||||||
let serverURL: string
|
let serverURL: string
|
||||||
let adminRoutes: ReturnType<typeof getRoutes>
|
let adminRoutes: ReturnType<typeof getRoutes>
|
||||||
@@ -76,6 +78,7 @@ describe('List View', () => {
|
|||||||
with300DocumentsUrl = new AdminUrlUtil(serverURL, with300DocumentsSlug)
|
with300DocumentsUrl = new AdminUrlUtil(serverURL, with300DocumentsSlug)
|
||||||
baseListFiltersUrl = new AdminUrlUtil(serverURL, 'base-list-filters')
|
baseListFiltersUrl = new AdminUrlUtil(serverURL, 'base-list-filters')
|
||||||
customViewsUrl = new AdminUrlUtil(serverURL, customViews1CollectionSlug)
|
customViewsUrl = new AdminUrlUtil(serverURL, customViews1CollectionSlug)
|
||||||
|
withListViewUrl = new AdminUrlUtil(serverURL, listDrawerSlug)
|
||||||
|
|
||||||
const context = await browser.newContext()
|
const context = await browser.newContext()
|
||||||
page = await context.newPage()
|
page = await context.newPage()
|
||||||
@@ -156,6 +159,20 @@ describe('List View', () => {
|
|||||||
`${adminRoutes.routes?.admin}/collections/posts/${id}`,
|
`${adminRoutes.routes?.admin}/collections/posts/${id}`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should hide create new button when allowCreate is false', async () => {
|
||||||
|
await page.goto(withListViewUrl.list)
|
||||||
|
|
||||||
|
const drawerButton = page.locator('button', { hasText: 'Select Posts' })
|
||||||
|
await expect(drawerButton).toBeVisible()
|
||||||
|
await drawerButton.click()
|
||||||
|
|
||||||
|
const drawer = page.locator('.drawer__content')
|
||||||
|
await expect(drawer).toBeVisible()
|
||||||
|
|
||||||
|
const createButton = page.locator('button', { hasText: 'Create New' })
|
||||||
|
await expect(createButton).toBeHidden()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('list view custom components', () => {
|
describe('list view custom components', () => {
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ export interface Config {
|
|||||||
'disable-duplicate': DisableDuplicate;
|
'disable-duplicate': DisableDuplicate;
|
||||||
'base-list-filters': BaseListFilter;
|
'base-list-filters': BaseListFilter;
|
||||||
with300documents: With300Document;
|
with300documents: With300Document;
|
||||||
|
'with-list-drawer': WithListDrawer;
|
||||||
'payload-locked-documents': PayloadLockedDocument;
|
'payload-locked-documents': PayloadLockedDocument;
|
||||||
'payload-preferences': PayloadPreference;
|
'payload-preferences': PayloadPreference;
|
||||||
'payload-migrations': PayloadMigration;
|
'payload-migrations': PayloadMigration;
|
||||||
@@ -106,6 +107,7 @@ export interface Config {
|
|||||||
'disable-duplicate': DisableDuplicateSelect<false> | DisableDuplicateSelect<true>;
|
'disable-duplicate': DisableDuplicateSelect<false> | DisableDuplicateSelect<true>;
|
||||||
'base-list-filters': BaseListFiltersSelect<false> | BaseListFiltersSelect<true>;
|
'base-list-filters': BaseListFiltersSelect<false> | BaseListFiltersSelect<true>;
|
||||||
with300documents: With300DocumentsSelect<false> | With300DocumentsSelect<true>;
|
with300documents: With300DocumentsSelect<false> | With300DocumentsSelect<true>;
|
||||||
|
'with-list-drawer': WithListDrawerSelect<false> | WithListDrawerSelect<true>;
|
||||||
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
||||||
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
||||||
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
|
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
|
||||||
@@ -445,6 +447,18 @@ export interface With300Document {
|
|||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "with-list-drawer".
|
||||||
|
*/
|
||||||
|
export interface WithListDrawer {
|
||||||
|
id: string;
|
||||||
|
title?: string | null;
|
||||||
|
description?: string | null;
|
||||||
|
number?: number | null;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-locked-documents".
|
* via the `definition` "payload-locked-documents".
|
||||||
@@ -519,6 +533,10 @@ export interface PayloadLockedDocument {
|
|||||||
| ({
|
| ({
|
||||||
relationTo: 'with300documents';
|
relationTo: 'with300documents';
|
||||||
value: string | With300Document;
|
value: string | With300Document;
|
||||||
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'with-list-drawer';
|
||||||
|
value: string | WithListDrawer;
|
||||||
} | null);
|
} | null);
|
||||||
globalSlug?: string | null;
|
globalSlug?: string | null;
|
||||||
user: {
|
user: {
|
||||||
@@ -822,6 +840,17 @@ export interface With300DocumentsSelect<T extends boolean = true> {
|
|||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "with-list-drawer_select".
|
||||||
|
*/
|
||||||
|
export interface WithListDrawerSelect<T extends boolean = true> {
|
||||||
|
title?: T;
|
||||||
|
description?: T;
|
||||||
|
number?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-locked-documents_select".
|
* via the `definition` "payload-locked-documents_select".
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ export const noApiViewCollectionSlug = 'collection-no-api-view'
|
|||||||
export const disableDuplicateSlug = 'disable-duplicate'
|
export const disableDuplicateSlug = 'disable-duplicate'
|
||||||
export const uploadCollectionSlug = 'uploads'
|
export const uploadCollectionSlug = 'uploads'
|
||||||
export const customFieldsSlug = 'custom-fields'
|
export const customFieldsSlug = 'custom-fields'
|
||||||
|
|
||||||
|
export const listDrawerSlug = 'with-list-drawer'
|
||||||
export const collectionSlugs = [
|
export const collectionSlugs = [
|
||||||
usersCollectionSlug,
|
usersCollectionSlug,
|
||||||
customViews1CollectionSlug,
|
customViews1CollectionSlug,
|
||||||
@@ -27,6 +29,7 @@ export const collectionSlugs = [
|
|||||||
noApiViewCollectionSlug,
|
noApiViewCollectionSlug,
|
||||||
customFieldsSlug,
|
customFieldsSlug,
|
||||||
disableDuplicateSlug,
|
disableDuplicateSlug,
|
||||||
|
listDrawerSlug,
|
||||||
]
|
]
|
||||||
|
|
||||||
export const customGlobalViews1GlobalSlug = 'custom-global-views-one'
|
export const customGlobalViews1GlobalSlug = 'custom-global-views-one'
|
||||||
|
|||||||
Reference in New Issue
Block a user