fix(next): unable to view trashed documents when group-by is enabled (#13300)

### What?

- Fixed an issue where group-by enabled collections with `trash: true`
were not showing trashed documents in the collection’s trash view.
- Ensured that the `trash` query argument is properly passed to the
`findDistinct` call within `handleGroupBy`, allowing trashed documents
to be included in grouped list views.

### Why?

Previously, when viewing the trash view of a collection with both
**group-by** and **trash** enabled, trashed documents would not appear.
This was caused by the `trash` argument not being forwarded to
`findDistinct` in `handleGroupBy`, which resulted in empty or incorrect
group-by results.

### How?

- Passed the `trash` flag through all relevant `findDistinct` and `find`
calls in `handleGroupBy`.
This commit is contained in:
Patrik
2025-07-28 14:29:04 -04:00
committed by GitHub
parent 5c94d2dc71
commit aff2ce1b9b
11 changed files with 150 additions and 13 deletions

View File

@@ -22,6 +22,7 @@ export const handleGroupBy = async ({
enableRowSelections,
query,
req,
trash = false,
user,
where: whereWithMergedSearch,
}: {
@@ -34,6 +35,7 @@ export const handleGroupBy = async ({
enableRowSelections?: boolean
query?: ListQuery
req: PayloadRequest
trash?: boolean
user: any
where: Where
}): Promise<{
@@ -88,6 +90,7 @@ export const handleGroupBy = async ({
populate,
req,
sort: query?.groupBy,
trash,
where: whereWithMergedSearch,
})
@@ -127,6 +130,7 @@ export const handleGroupBy = async ({
// Note: if we wanted to enable table-by-table sorting, we could use this:
// sort: query?.queryByGroup?.[valueOrRelationshipID]?.sort,
sort: query?.sort,
trash,
user,
where: {
...(whereWithMergedSearch || {}),

View File

@@ -205,6 +205,7 @@ export const renderListView = async (
enableRowSelections,
query,
req,
trash: query?.trash === true,
user,
where: whereWithMergedSearch,
}))

View File

@@ -11,13 +11,14 @@ import { findDistinctOperation } from '../operations/findDistinct.js'
export const findDistinctHandler: PayloadHandler = async (req) => {
const collection = getRequestCollection(req)
const { depth, field, limit, page, sort, where } = req.query as {
const { depth, field, limit, page, sort, trash, where } = req.query as {
depth?: string
field?: string
limit?: string
page?: string
sort?: string
sortOrder?: string
trash?: string
where?: Where
}
@@ -33,6 +34,7 @@ export const findDistinctHandler: PayloadHandler = async (req) => {
page: isNumber(page) ? Number(page) : undefined,
req,
sort: typeof sort === 'string' ? sort.split(',') : undefined,
trash: trash === 'true',
where,
})

View File

@@ -9,7 +9,7 @@ import { docAccessHandler } from './docAccess.js'
import { duplicateHandler } from './duplicate.js'
import { findHandler } from './find.js'
import { findByIDHandler } from './findByID.js'
import { findDistinctHandler } from './findDistinct.js'
// import { findDistinctHandler } from './findDistinct.js'
import { findVersionByIDHandler } from './findVersionByID.js'
import { findVersionsHandler } from './findVersions.js'
import { previewHandler } from './preview.js'

View File

@@ -12,6 +12,7 @@ import { sanitizeWhereQuery } from '../../database/sanitizeWhereQuery.js'
import { APIError } from '../../errors/APIError.js'
import { Forbidden } from '../../errors/Forbidden.js'
import { relationshipPopulationPromise } from '../../fields/hooks/afterRead/relationshipPopulationPromise.js'
import { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js'
import { getFieldByPath } from '../../utilities/getFieldByPath.js'
import { killTransaction } from '../../utilities/killTransaction.js'
import { buildAfterOperation } from './utils.js'
@@ -29,6 +30,7 @@ export type Arguments = {
req?: PayloadRequest
showHiddenFields?: boolean
sort?: Sort
trash?: boolean
where?: Where
}
export const findDistinctOperation = async (
@@ -60,6 +62,7 @@ export const findDistinctOperation = async (
overrideAccess,
populate,
showHiddenFields = false,
trash = false,
where,
} = args
@@ -96,9 +99,16 @@ export const findDistinctOperation = async (
// Find Distinct
// /////////////////////////////////////
const fullWhere = combineQueries(where!, accessResult!)
let fullWhere = combineQueries(where!, accessResult!)
sanitizeWhereQuery({ fields: collectionConfig.flattenedFields, payload, where: fullWhere })
// Exclude trashed documents when trash: false
fullWhere = appendNonTrashedFilter({
enableTrash: collectionConfig.trash,
trash,
where: fullWhere,
})
await validateQueryPaths({
collectionConfig,
overrideAccess: overrideAccess!,

View File

@@ -83,6 +83,15 @@ export type Options<
* @example ['group', '-createdAt'] // sort by 2 fields, ASC group and DESC createdAt
*/
sort?: Sort
/**
* When set to `true`, the query will include both normal and trashed documents.
* To query only trashed documents, pass `trash: true` and combine with a `where` clause filtering by `deletedAt`.
* By default (`false`), the query will only include normal documents and exclude those with a `deletedAt` field.
*
* This argument has no effect unless `trash` is enabled on the collection.
* @default false
*/
trash?: boolean
/**
* If you set `overrideAccess` to `false`, you can pass a user to use against the access control checks.
*/
@@ -111,6 +120,7 @@ export async function findDistinct<
populate,
showHiddenFields,
sort,
trash = false,
where,
} = options
const collection = payload.collections[collectionSlug]
@@ -133,6 +143,7 @@ export async function findDistinct<
req: await createLocalReq(options as CreateLocalReqOptions, payload),
showHiddenFields,
sort,
trash,
where,
}) as Promise<PaginatedDistinctDocs<Record<TField, DataFromCollectionSlug<TSlug>[TField]>>>
}