feat(next): add support for custom collection views#16243
feat(next): add support for custom collection views#16243
Conversation
- Update CollectionAdminOptions type to allow custom views at collection level - Create getCustomCollectionViewByRoute helper function - Modify getRouteData.ts to check for custom collection views before defaulting to edit views - Add test collection with custom grid view - Add test to verify custom collection view routing Co-authored-by: robinscholz <8195463+robinscholz@users.noreply.github.com>
Co-authored-by: robinscholz <8195463+robinscholz@users.noreply.github.com>
Co-authored-by: robinscholz <8195463+robinscholz@users.noreply.github.com>
- Add null check for views object - Change viewKey return value from null to undefined for consistency - Address code cleanliness issues Co-authored-by: robinscholz <8195463+robinscholz@users.noreply.github.com>
Reordered the routing logic so that folder views are checked before custom collection views. Order is now: trash → folders → custom views → edit views Co-authored-by: robinscholz <8195463+robinscholz@users.noreply.github.com>
…inition Changed the index signature to use a union type that includes undefined, allowing it to be compatible with optional properties like edit and list. This fixes the build error in @payloadcms/plugin-search and other packages. Co-authored-by: robinscholz <8195463+robinscholz@users.noreply.github.com>
feat(next): support custom collection-level views
📦 esbuild Bundle Analysis for payloadThis analysis was generated by esbuild-bundle-analyzer. 🤖
Largest pathsThese visualization shows top 20 largest paths in the bundle.Meta file: packages/next/meta_index.json, Out file: esbuild/index.js
Meta file: packages/payload/meta_index.json, Out file: esbuild/index.js
Meta file: packages/payload/meta_shared.json, Out file: esbuild/exports/shared.js
Meta file: packages/richtext-lexical/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
Meta file: packages/ui/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
Meta file: packages/ui/meta_shared.json, Out file: esbuild/exports/shared_optimized/index.js
DetailsNext to the size is how much the size has increased or decreased compared with the base branch of this PR.
|
| const adminView = view as AdminViewConfig | ||
| const viewPath = `${baseRoute}${adminView.path}` | ||
|
|
||
| return isPathMatchingRoute({ |
There was a problem hiding this comment.
In packages/next/src/views/Root/isPathMatchingRoute.ts#L38
if (!exact) {
return viewRoute.startsWith(currentRoute) // ← WRONG direction
}
Should this be currentRoute.startsWith(viewRoute)?
The intent is "does the current URL begin with the view's path?" but the code checks the opposite.
In practice this only bites if a user sets exact: false (or omits exact) and then navigates to a sub-path like /grid/detail. The PR usage example always shows exact: true, so the happy path isn't broken. But prefix matching is silently broken.
| viewKey: null | string | ||
| } => { | ||
| const currentRoute = | ||
| adminRoute === '/' ? currentRouteWithAdmin : currentRouteWithAdmin.replace(adminRoute, '') |
There was a problem hiding this comment.
currentRouteWithAdmin.replace(adminRoute, '')
String.replace replaces the first occurrence, not a proper prefix. If adminRoute = '/app' and the URL is /apparel/collections/foo/grid, this incorrectly strips /app from inside the word, yielding arel/collections/foo/grid.
The safer approach is slice(adminRoute.length) guarded by a startsWith check.
More of a correctness issue.
| }, | ||
| } | ||
|
|
||
| describe('getCustomCollectionViewByRoute', () => { |
There was a problem hiding this comment.
Every test in the spec uses exact: true.
The inverted prefix logic in isPathMatchingRoute.ts doesn't have test coverage.
A test with exact: false and a sub-path URL would probably catch a bug mentioned in getCustomCollectionViewByRoute.
| | 'trash' | ||
| | 'verify' | ||
| | 'version' | ||
| | ({} & string) |
There was a problem hiding this comment.
Is this needed?
{} & string already makes ViewTypes accept any string, but you're also doing string | ViewTypes in packages/next/src/views/Root/getRouteData.ts#L87 with:
viewType?: string | ViewTypes
I think we just need one of the two
Originally this PR with extra changes: #15410
admin.components.views[key]with aComponentandpath— resolves Can’t add custom view under new path to collection #15386console.warnwhen a custom view is misconfigured without apathpropertyUsage