public-demo icon indicating copy to clipboard operation
public-demo copied to clipboard

Archive Block pagination doesn't work correctly for posts

Open jyavorska opened this issue 1 year ago • 2 comments

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 avatar Feb 03 '24 20:02 jyavorska

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 avatar Feb 04 '24 12:02 jyavorska

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.

jyavorska avatar Feb 04 '24 14:02 jyavorska