payloadcms / public-demo

The official public demo for Payload
https://demo.payloadcms.com
152 stars 74 forks source link

Archive Block pagination doesn't work correctly for posts #40

Open jyavorska opened 8 months ago

jyavorska commented 8 months ago

Seems to work fine for projects, interestingly.

  1. Either add new posts or set pagination below 3 on the archive block
  2. As you switch through pages, observe that (some of) the same items are showing up on multiple pages. This prevents you from seeing all the posts as you paginate through.

I played with it a bit but haven't yet figured out exactly what's going on as I'm still learning payload (edit: I think I found the issue in https://github.com/payloadcms/public-demo/issues/40#issuecomment-1925760950). If I find anything I'll share it here. I'm at least fairly certain that it's something on the server side rather than the client app.

https://github.com/payloadcms/public-demo/assets/3529318/77e0db00-9d0f-4334-b4a2-ad5215382efc

jyavorska commented 8 months ago

I can confirm I'm seeing the duplicate posts when visiting URLs like the following, so it's coming from the backend rather than a frontend bug.

http://localhost:3000/api/posts?depth=0&limit=3&page=1&sort=-publishedDate

http://localhost:3000/api/posts?depth=0&limit=3&page=2&sort=-publishedDate

The issue goes away when sorting by id instead. I confirmed that I don't have any duplicate publish dates that might cause different search results each time:

image

https://github.com/payloadcms/payload/discussions/2409 and https://github.com/payloadcms/payload/issues/3209 may be related

jyavorska commented 8 months ago

The fundamental issue seems to be that a field called publishedDate is used by projects and pages, and this is what the component expects to sort by, but posts calls the field publishedOn instead. To fix this locally I updated references to publishedOn to publishedDate everywhere it was used, generated types, and ran the following migration:

import type { MigrateDownArgs, MigrateUpArgs } from '@payloadcms/db-mongodb'

export async function up({ payload }: MigrateUpArgs): Promise<void> {
  const postsCollection = await payload.find({ collection: 'posts', pagination: false })

  for (const doc of postsCollection.docs) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const oldDoc = doc as any
    if (oldDoc.publishedOn) {
      await payload.update({
        id: doc.id,
        collection: 'posts',
        data: { publishedDate: oldDoc.publishedOn },
        overrideAccess: true,
      })
    }
  }
}

export async function down({ payload }: MigrateDownArgs): Promise<void> {
  const postsCollection = await payload.find({ collection: 'posts', pagination: false })

  for (const doc of postsCollection.docs) {
    if (doc.publishedDate) {
      await payload.update({
        id: doc.id,
        collection: 'posts',
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        data: { publishedDate: null, publishedOn: doc.publishedDate } as any,
        overrideAccess: true,
      })
    }
  }
}

For the public-demo project, seems the easiest would be just to rename the field so it's consistent across collections, but maybe it was different for a reason. I'd be happy to make a PR if someone on the team confirms that you want them consistent.