fix: duplicate with upload collections (#8552)
Fixes the duplicate operation with uploads Enables duplicate for upload collections by default
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -314,3 +314,6 @@ test/app/(payload)/admin/importMap.js
|
||||
/test/app/(payload)/admin/importMap.js
|
||||
test/pnpm-lock.yaml
|
||||
test/databaseAdapter.js
|
||||
/filename-compound-index
|
||||
/media-with-relation-preview
|
||||
/media-without-relation-preview
|
||||
|
||||
@@ -130,9 +130,6 @@ export const sanitizeCollection = async (
|
||||
// sanitize fields for reserved names
|
||||
sanitizeUploadFields(sanitized.fields, sanitized)
|
||||
|
||||
// disable duplicate for uploads by default
|
||||
sanitized.disableDuplicate = sanitized.disableDuplicate || true
|
||||
|
||||
sanitized.upload.bulkUpload = sanitized.upload?.bulkUpload ?? true
|
||||
sanitized.upload.staticDir = sanitized.upload.staticDir || sanitized.slug
|
||||
sanitized.admin.useAsTitle =
|
||||
@@ -162,7 +159,7 @@ export const sanitizeCollection = async (
|
||||
}
|
||||
|
||||
// disable duplicate for auth enabled collections by default
|
||||
sanitized.disableDuplicate = sanitized.disableDuplicate || true
|
||||
sanitized.disableDuplicate = sanitized.disableDuplicate ?? true
|
||||
|
||||
if (!sanitized.auth.strategies) {
|
||||
sanitized.auth.strategies = []
|
||||
|
||||
@@ -16,6 +16,8 @@ import { afterRead } from '../../fields/hooks/afterRead/index.js'
|
||||
import { beforeChange } from '../../fields/hooks/beforeChange/index.js'
|
||||
import { beforeDuplicate } from '../../fields/hooks/beforeDuplicate/index.js'
|
||||
import { beforeValidate } from '../../fields/hooks/beforeValidate/index.js'
|
||||
import { generateFileData } from '../../uploads/generateFileData.js'
|
||||
import { uploadFiles } from '../../uploads/uploadFiles.js'
|
||||
import { commitTransaction } from '../../utilities/commitTransaction.js'
|
||||
import { initTransaction } from '../../utilities/initTransaction.js'
|
||||
import { killTransaction } from '../../utilities/killTransaction.js'
|
||||
@@ -129,7 +131,7 @@ export const duplicateOperation = async <TSlug extends CollectionSlug>(
|
||||
|
||||
let result
|
||||
|
||||
const originalDoc = await afterRead({
|
||||
let originalDoc = await afterRead({
|
||||
collection: collectionConfig,
|
||||
context: req.context,
|
||||
depth: 0,
|
||||
@@ -143,6 +145,18 @@ export const duplicateOperation = async <TSlug extends CollectionSlug>(
|
||||
showHiddenFields: true,
|
||||
})
|
||||
|
||||
const { data: newFileData, files: filesToUpload } = await generateFileData({
|
||||
collection: args.collection,
|
||||
config: req.payload.config,
|
||||
data: originalDoc,
|
||||
operation: 'create',
|
||||
overwriteExistingFiles: 'forceDisable',
|
||||
req,
|
||||
throwOnMissingFile: true,
|
||||
})
|
||||
|
||||
originalDoc = newFileData
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Create Access
|
||||
// /////////////////////////////////////
|
||||
@@ -231,6 +245,14 @@ export const duplicateOperation = async <TSlug extends CollectionSlug>(
|
||||
// Create / Update
|
||||
// /////////////////////////////////////
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Write files to local storage
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!collectionConfig.upload.disableLocalStorage) {
|
||||
await uploadFiles(payload, filesToUpload, req)
|
||||
}
|
||||
|
||||
const versionDoc = await payload.db.create({
|
||||
collection: collectionConfig.slug,
|
||||
data: result,
|
||||
|
||||
@@ -44,7 +44,7 @@ export async function duplicate<TSlug extends CollectionSlug>(
|
||||
)
|
||||
}
|
||||
|
||||
if (collection.config.disableDuplicate === false) {
|
||||
if (collection.config.disableDuplicate === true) {
|
||||
throw new APIError(
|
||||
`The collection with slug ${String(collectionSlug)} cannot be duplicated.`,
|
||||
400,
|
||||
|
||||
@@ -27,7 +27,8 @@ type Args<T> = {
|
||||
data: T
|
||||
operation: 'create' | 'update'
|
||||
originalDoc?: T
|
||||
overwriteExistingFiles?: boolean
|
||||
/** pass forceDisable to not overwrite existing files even if they already exist in `data` */
|
||||
overwriteExistingFiles?: 'forceDisable' | boolean
|
||||
req: PayloadRequest
|
||||
throwOnMissingFile?: boolean
|
||||
}
|
||||
@@ -85,20 +86,28 @@ export const generateFileData = async <T>({
|
||||
const filePath = `${staticPath}/${filename}`
|
||||
const response = await getFileByPath(filePath)
|
||||
file = response
|
||||
overwriteExistingFiles = true
|
||||
if (overwriteExistingFiles !== 'forceDisable') {
|
||||
overwriteExistingFiles = true
|
||||
}
|
||||
} else if (filename && url) {
|
||||
file = await getExternalFile({
|
||||
data: data as FileData,
|
||||
req,
|
||||
uploadConfig: collectionConfig.upload,
|
||||
})
|
||||
overwriteExistingFiles = true
|
||||
if (overwriteExistingFiles !== 'forceDisable') {
|
||||
overwriteExistingFiles = true
|
||||
}
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
throw new FileRetrievalError(req.t, err instanceof Error ? err.message : undefined)
|
||||
}
|
||||
}
|
||||
|
||||
if (overwriteExistingFiles === 'forceDisable') {
|
||||
overwriteExistingFiles = false
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
if (throwOnMissingFile) {
|
||||
throw new MissingFile(req.t)
|
||||
|
||||
@@ -279,7 +279,7 @@ export const DocumentControls: React.FC<{
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
{!collectionConfig.disableDuplicate && isEditing && (
|
||||
{collectionConfig.disableDuplicate !== true && isEditing && (
|
||||
<DuplicateDocument
|
||||
id={id.toString()}
|
||||
onDuplicate={onDuplicate}
|
||||
|
||||
@@ -17,8 +17,8 @@ import {
|
||||
enlargeSlug,
|
||||
focalNoSizesSlug,
|
||||
mediaSlug,
|
||||
mediaWithRelationPreviewSlug,
|
||||
mediaWithoutRelationPreviewSlug,
|
||||
mediaWithRelationPreviewSlug,
|
||||
reduceSlug,
|
||||
relationPreviewSlug,
|
||||
relationSlug,
|
||||
|
||||
@@ -779,6 +779,31 @@ describe('Collections - Uploads', () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Duplicate', () => {
|
||||
it('should duplicate upload collection doc', async () => {
|
||||
const filePath = path.resolve(dirname, './image.png')
|
||||
const file = await getFileByPath(filePath)
|
||||
file.name = 'file-to-duplicate.png'
|
||||
|
||||
const mediaDoc = await payload.create({
|
||||
collection: 'media',
|
||||
data: {},
|
||||
file,
|
||||
})
|
||||
|
||||
expect(mediaDoc).toBeDefined()
|
||||
|
||||
const duplicatedDoc = await payload.duplicate({
|
||||
collection: 'media',
|
||||
id: mediaDoc.id,
|
||||
})
|
||||
|
||||
const expectedPath = path.join(dirname, './media')
|
||||
|
||||
expect(await fileExists(path.join(expectedPath, duplicatedDoc.filename))).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
async function fileExists(fileName: string): Promise<boolean> {
|
||||
|
||||
Reference in New Issue
Block a user