fix: duplicate with upload collections (#8552)

Fixes the duplicate operation with uploads
Enables duplicate for upload collections by default
This commit is contained in:
Sasha
2024-10-04 21:46:41 +03:00
committed by GitHub
parent e4a413eb9a
commit 400293b8ee
8 changed files with 67 additions and 11 deletions

3
.gitignore vendored
View File

@@ -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

View File

@@ -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 = []

View File

@@ -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,

View File

@@ -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,

View File

@@ -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)

View File

@@ -279,7 +279,7 @@ export const DocumentControls: React.FC<{
)}
</Fragment>
)}
{!collectionConfig.disableDuplicate && isEditing && (
{collectionConfig.disableDuplicate !== true && isEditing && (
<DuplicateDocument
id={id.toString()}
onDuplicate={onDuplicate}

View File

@@ -17,8 +17,8 @@ import {
enlargeSlug,
focalNoSizesSlug,
mediaSlug,
mediaWithRelationPreviewSlug,
mediaWithoutRelationPreviewSlug,
mediaWithRelationPreviewSlug,
reduceSlug,
relationPreviewSlug,
relationSlug,

View File

@@ -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> {