From e90ff72b3742c34d10745b9349a1359a8ecca826 Mon Sep 17 00:00:00 2001 From: Dan Ribbens Date: Tue, 15 Apr 2025 12:09:55 -0400 Subject: [PATCH] fix: reordering draft documents causes data loss (#12109) Re-ordering documents with drafts uses `payload.update()` with `select: { id: true }` and that causes draft versions of those docs to be updated without any data. I've removed the `select` optimization to prevent data loss. Fixes #12097 --- .../payload/src/config/orderable/index.ts | 1 - test/sort/collections/Drafts/index.ts | 1 + test/sort/int.spec.ts | 118 +++++++++++++++++- 3 files changed, 118 insertions(+), 2 deletions(-) diff --git a/packages/payload/src/config/orderable/index.ts b/packages/payload/src/config/orderable/index.ts index be3cdc53c..c09de82a1 100644 --- a/packages/payload/src/config/orderable/index.ts +++ b/packages/payload/src/config/orderable/index.ts @@ -257,7 +257,6 @@ export const addOrderableEndpoint = (config: SanitizedConfig) => { }, depth: 0, req, - select: { id: true }, }) } diff --git a/test/sort/collections/Drafts/index.ts b/test/sort/collections/Drafts/index.ts index a6d73ae2d..eab76ebcb 100644 --- a/test/sort/collections/Drafts/index.ts +++ b/test/sort/collections/Drafts/index.ts @@ -7,6 +7,7 @@ export const DraftsCollection: CollectionConfig = { admin: { useAsTitle: 'text', }, + orderable: true, versions: { drafts: true, }, diff --git a/test/sort/int.spec.ts b/test/sort/int.spec.ts index 12689c339..0fea47ee9 100644 --- a/test/sort/int.spec.ts +++ b/test/sort/int.spec.ts @@ -4,9 +4,10 @@ import path from 'path' import { fileURLToPath } from 'url' import type { NextRESTClient } from '../helpers/NextRESTClient.js' -import type { Orderable, OrderableJoin } from './payload-types.js' +import type { Draft, Orderable, OrderableJoin } from './payload-types.js' import { initPayloadInt } from '../helpers/initPayloadInt.js' +import { draftsSlug } from './collections/Drafts/index.js' import { orderableSlug } from './collections/Orderable/index.js' import { orderableJoinSlug } from './collections/OrderableJoin/index.js' @@ -330,6 +331,121 @@ describe('Sort', () => { }) }) + describe('Orderable', () => { + let orderable1: Orderable + let orderable2: Orderable + let orderableDraft1: Draft + let orderableDraft2: Draft + beforeAll(async () => { + orderable1 = await payload.create({ + collection: orderableSlug, + data: { + title: 'Orderable 1', + }, + }) + orderable2 = await payload.create({ + collection: orderableSlug, + data: { + title: 'Orderable 2', + }, + }) + orderableDraft1 = await payload.create({ + collection: draftsSlug, + data: { + text: 'Orderable 1', + _status: 'draft', + }, + }) + orderableDraft2 = await payload.create({ + collection: draftsSlug, + data: { + text: 'Orderable 2', + _status: 'draft', + }, + }) + }) + + it('should set order by default', async () => { + const ordered = await payload.find({ + collection: orderableSlug, + where: { + title: { + contains: 'Orderable ', + }, + }, + }) + + expect(orderable1._order).toBeDefined() + expect(orderable2._order).toBeDefined() + expect(parseInt(orderable1._order, 16)).toBeLessThan(parseInt(orderable2._order, 16)) + expect(ordered.docs[0].id).toStrictEqual(orderable1.id) + expect(ordered.docs[1].id).toStrictEqual(orderable2.id) + }) + + it('should allow reordering with REST API', async () => { + const res = await restClient.POST('/reorder', { + body: JSON.stringify({ + collectionSlug: orderableSlug, + docsToMove: [orderable1.id], + newKeyWillBe: 'greater', + orderableFieldName: '_order', + target: { + id: orderable2.id, + key: orderable2._order, + }, + }), + }) + + expect(res.status).toStrictEqual(200) + + const ordered = await payload.find({ + collection: 'orderable', + where: { + title: { + contains: 'Orderable ', + }, + }, + }) + + expect(parseInt(ordered.docs[0]._order, 16)).toBeLessThan( + parseInt(ordered.docs[1]._order, 16), + ) + }) + + it('should allow reordering with REST API with drafts enabled', async () => { + const res = await restClient.POST('/reorder', { + body: JSON.stringify({ + collectionSlug: draftsSlug, + docsToMove: [orderableDraft1.id], + newKeyWillBe: 'greater', + orderableFieldName: '_order', + target: { + id: orderableDraft2.id, + key: orderableDraft2._order, + }, + }), + }) + + expect(res.status).toStrictEqual(200) + + const ordered = await payload.find({ + collection: draftsSlug, + draft: true, + where: { + text: { + contains: 'Orderable ', + }, + }, + }) + + expect(ordered.docs).toHaveLength(2) + + expect(parseInt(ordered.docs[0]._order, 16)).toBeLessThan( + parseInt(ordered.docs[1]._order, 16), + ) + }) + }) + describe('Orderable join', () => { let related: OrderableJoin let orderable1: Orderable