feat(plugin-import-export): adds limit and page fields to export options (#13380)
### What: This PR adds `limit` and `page` fields to the export options, allowing users to control the number of documents exported and the page from which to start the export. It also enforces that limit must be a positive multiple of 100. ### Why: This feature is needed to provide pagination support for large exports, enabling users to export manageable chunks of data rather than the entire dataset at once. Enforcing multiples-of-100 for `limit` ensures consistent chunking behavior and prevents unexpected export issues. ### How: - The `limit` field determines the maximum number of documents to export and **must be a positive multiple of 100**. - The `page` field defines the starting page of the export and is displayed only when a `limit` is specified. - If `limit` is cleared, the `page` resets to 1 to maintain consistency. - Export logic was adjusted to respect the `limit` and `page` values when fetching documents. --------- Co-authored-by: Patrik Kozak <35232443+PatrikKozak@users.noreply.github.com>
This commit is contained in:
@@ -87,6 +87,129 @@ describe('@payloadcms/plugin-import-export', () => {
|
||||
expect(data[0].updatedAt).toBeDefined()
|
||||
})
|
||||
|
||||
it('should create a file for collection csv with all documents when limit 0', async () => {
|
||||
let doc = await payload.create({
|
||||
collection: 'exports',
|
||||
user,
|
||||
data: {
|
||||
collectionSlug: 'pages',
|
||||
format: 'csv',
|
||||
limit: 0,
|
||||
},
|
||||
})
|
||||
|
||||
doc = await payload.findByID({
|
||||
collection: 'exports',
|
||||
id: doc.id,
|
||||
})
|
||||
|
||||
expect(doc.filename).toBeDefined()
|
||||
const expectedPath = path.join(dirname, './uploads', doc.filename as string)
|
||||
const data = await readCSV(expectedPath)
|
||||
|
||||
expect(data).toHaveLength(250)
|
||||
})
|
||||
|
||||
it('should create a file for collection csv with all documents when no limit', async () => {
|
||||
let doc = await payload.create({
|
||||
collection: 'exports',
|
||||
user,
|
||||
data: {
|
||||
collectionSlug: 'pages',
|
||||
format: 'csv',
|
||||
},
|
||||
})
|
||||
|
||||
doc = await payload.findByID({
|
||||
collection: 'exports',
|
||||
id: doc.id,
|
||||
})
|
||||
|
||||
expect(doc.filename).toBeDefined()
|
||||
const expectedPath = path.join(dirname, './uploads', doc.filename as string)
|
||||
const data = await readCSV(expectedPath)
|
||||
|
||||
expect(data).toHaveLength(250)
|
||||
})
|
||||
|
||||
it('should create a file for collection csv from limit and page 1', async () => {
|
||||
let doc = await payload.create({
|
||||
collection: 'exports',
|
||||
user,
|
||||
data: {
|
||||
collectionSlug: 'pages',
|
||||
format: 'csv',
|
||||
limit: 100,
|
||||
page: 1,
|
||||
},
|
||||
})
|
||||
|
||||
doc = await payload.findByID({
|
||||
collection: 'exports',
|
||||
id: doc.id,
|
||||
})
|
||||
|
||||
expect(doc.filename).toBeDefined()
|
||||
const expectedPath = path.join(dirname, './uploads', doc.filename as string)
|
||||
const data = await readCSV(expectedPath)
|
||||
|
||||
expect(data[0].id).toBeDefined()
|
||||
expect(data[0].title).toStrictEqual('Polymorphic 4')
|
||||
})
|
||||
|
||||
it('should create a file for collection csv from limit and page 2', async () => {
|
||||
let doc = await payload.create({
|
||||
collection: 'exports',
|
||||
user,
|
||||
data: {
|
||||
collectionSlug: 'pages',
|
||||
format: 'csv',
|
||||
limit: 100,
|
||||
page: 2,
|
||||
},
|
||||
})
|
||||
|
||||
doc = await payload.findByID({
|
||||
collection: 'exports',
|
||||
id: doc.id,
|
||||
})
|
||||
|
||||
expect(doc.filename).toBeDefined()
|
||||
const expectedPath = path.join(dirname, './uploads', doc.filename as string)
|
||||
const data = await readCSV(expectedPath)
|
||||
|
||||
expect(data[0].id).toBeDefined()
|
||||
expect(data[0].title).toStrictEqual('Doc 149')
|
||||
})
|
||||
|
||||
it('should not create a file for collection csv when limit < 0', async () => {
|
||||
await expect(
|
||||
payload.create({
|
||||
collection: 'exports',
|
||||
user,
|
||||
data: {
|
||||
collectionSlug: 'pages',
|
||||
format: 'csv',
|
||||
limit: -1,
|
||||
},
|
||||
}),
|
||||
).rejects.toThrow(/Limit/)
|
||||
})
|
||||
|
||||
it('should not create a file for collection csv when limit is not a multiple of 100', async () => {
|
||||
await expect(
|
||||
payload.create({
|
||||
collection: 'exports',
|
||||
user,
|
||||
data: {
|
||||
collectionSlug: 'pages',
|
||||
format: 'csv',
|
||||
limit: 99,
|
||||
},
|
||||
}),
|
||||
).rejects.toThrow(/Limit/)
|
||||
})
|
||||
|
||||
it('should create a file for collection csv with draft data', async () => {
|
||||
const draftPage = await payload.create({
|
||||
collection: 'pages',
|
||||
|
||||
@@ -268,6 +268,7 @@ export interface Export {
|
||||
name?: string | null;
|
||||
format?: ('csv' | 'json') | null;
|
||||
limit?: number | null;
|
||||
page?: number | null;
|
||||
sort?: string | null;
|
||||
locale?: ('all' | 'en' | 'es' | 'de') | null;
|
||||
drafts?: ('yes' | 'no') | null;
|
||||
@@ -304,6 +305,7 @@ export interface ExportsTask {
|
||||
name?: string | null;
|
||||
format?: ('csv' | 'json') | null;
|
||||
limit?: number | null;
|
||||
page?: number | null;
|
||||
sort?: string | null;
|
||||
locale?: ('all' | 'en' | 'es' | 'de') | null;
|
||||
drafts?: ('yes' | 'no') | null;
|
||||
@@ -605,6 +607,7 @@ export interface ExportsSelect<T extends boolean = true> {
|
||||
name?: T;
|
||||
format?: T;
|
||||
limit?: T;
|
||||
page?: T;
|
||||
sort?: T;
|
||||
locale?: T;
|
||||
drafts?: T;
|
||||
@@ -632,6 +635,7 @@ export interface ExportsTasksSelect<T extends boolean = true> {
|
||||
name?: T;
|
||||
format?: T;
|
||||
limit?: T;
|
||||
page?: T;
|
||||
sort?: T;
|
||||
locale?: T;
|
||||
drafts?: T;
|
||||
@@ -723,6 +727,7 @@ export interface TaskCreateCollectionExport {
|
||||
name?: string | null;
|
||||
format?: ('csv' | 'json') | null;
|
||||
limit?: number | null;
|
||||
page?: number | null;
|
||||
sort?: string | null;
|
||||
locale?: ('all' | 'en' | 'es' | 'de') | null;
|
||||
drafts?: ('yes' | 'no') | null;
|
||||
|
||||
@@ -26,6 +26,15 @@ export const seed = async (payload: Payload): Promise<boolean> => {
|
||||
posts.push(post)
|
||||
}
|
||||
// create pages
|
||||
for (let i = 0; i < 195; i++) {
|
||||
await payload.create({
|
||||
collection: 'pages',
|
||||
data: {
|
||||
title: `Doc ${i}`,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await payload.create({
|
||||
collection: 'pages',
|
||||
|
||||
Reference in New Issue
Block a user