diff --git a/packages/nc-gui/components/cell/attachment/utils.ts b/packages/nc-gui/components/cell/attachment/utils.ts index 0e53d235c4..70b8fb1f8d 100644 --- a/packages/nc-gui/components/cell/attachment/utils.ts +++ b/packages/nc-gui/components/cell/attachment/utils.ts @@ -1,4 +1,5 @@ import type { AttachmentReqType, AttachmentType } from 'nocodb-sdk' +import { populateUniqueFileName } from 'nocodb-sdk' import DOMPurify from 'isomorphic-dompurify' import RenameFile from './RenameFile.vue' import { @@ -161,7 +162,7 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState( } else { const fileName = populateUniqueFileName( (file as AttachmentReqType).fileName ?? '', - [...attachments.value, ...imageUrls], + [...attachments.value, ...imageUrls].map((fn) => fn?.title || fn?.fileName || 'image'), (file as File)?.type || (file as AttachmentReqType)?.mimetype || '', ) @@ -225,7 +226,7 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState( ...uploadedFile, title: populateUniqueFileName( uploadedFile?.title, - [...attachments.value, ...newAttachments], + [...attachments.value, ...newAttachments].map((fn) => fn?.title || fn?.fileName || 'image'), uploadedFile?.mimetype, ), }) diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts index 5ca19962a0..1d147c0296 100644 --- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts +++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts @@ -1,6 +1,6 @@ import dayjs from 'dayjs' import type { AttachmentType, ColumnType, LinkToAnotherRecordType, SelectOptionsType } from 'nocodb-sdk' -import { UITypes } from 'nocodb-sdk' +import { UITypes, populateUniqueFileName } from 'nocodb-sdk' import type { AppInfo } from '~/composables/useGlobal' import { isBt, isMm, parseProp } from '#imports' @@ -203,7 +203,11 @@ export default function convertCellData( for (const att of attachments) { newAttachments.push({ ...att, - title: populateUniqueFileName(att?.title, [...oldAttachments, ...newAttachments], att?.mimetype), + title: populateUniqueFileName( + att?.title, + [...oldAttachments, ...newAttachments].map((fn) => fn?.title || fn?.fileName || 'image'), + att?.mimetype, + ), }) } return JSON.stringify([...oldAttachments, ...newAttachments]) diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index 3cedc82563..f2afe20969 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -11,7 +11,15 @@ import type { UserFieldRecordType, ViewType, } from 'nocodb-sdk' -import { UITypes, dateFormats, isDateMonthFormat, isSystemColumn, isVirtualCol, timeFormats } from 'nocodb-sdk' +import { + UITypes, + dateFormats, + isDateMonthFormat, + isSystemColumn, + isVirtualCol, + timeFormats, + populateUniqueFileName, +} from 'nocodb-sdk' import { parse } from 'papaparse' import type { Cell } from './cellRange' import { CellRange } from './cellRange' @@ -1253,7 +1261,7 @@ export function useMultiSelect( ...uploadedFile, title: populateUniqueFileName( uploadedFile?.title, - [...handleParseAttachmentCellData(oldValue), ...newAttachments], + [...handleParseAttachmentCellData(oldValue), ...newAttachments].map((fn) => fn?.title || fn?.fileName || 'image'), uploadedFile?.mimetype, ), }) diff --git a/packages/nc-gui/utils/fileUtils.ts b/packages/nc-gui/utils/fileUtils.ts index da3bdf45f9..521bbf6e7c 100644 --- a/packages/nc-gui/utils/fileUtils.ts +++ b/packages/nc-gui/utils/fileUtils.ts @@ -77,21 +77,3 @@ export function extractImageSrcFromRawHtml(rawText: string) { return imgElement.getAttribute('src') } } - -export function populateUniqueFileName(fn: string, attachments: any[], mimeType: string) { - if (!mimeType) return fn - - // If the image extension is not present, the while loop will go into an infinite loop. So, add the extension first if not present. - if (!fn?.endsWith(mimeType.split('/')[1])) { - fn = `${fn}.${mimeType.split('/')[1]}` - } - - let c = 1 - let originalFn = fn - - while (attachments.some((att) => att?.title === fn || att?.fileName === fn)) { - const match = fn.match(/^(.+?)(\(\d+\))?(\.[^.]+)$/) - fn = match ? `${match[1]}(${c++})${match[3]}` : `${originalFn}(${c++})` - } - return fn -} diff --git a/packages/nocodb-sdk/src/lib/helperFunctions.ts b/packages/nocodb-sdk/src/lib/helperFunctions.ts index 527e479af6..b9fa956923 100644 --- a/packages/nocodb-sdk/src/lib/helperFunctions.ts +++ b/packages/nocodb-sdk/src/lib/helperFunctions.ts @@ -97,6 +97,36 @@ const getAvailableRollupForUiType = (type: string) => { } }; +function populateUniqueFileName( + fileName: string, + attachments: string[], + mimeType: string +) { + if (!mimeType) return fileName; + + // If the file extension is not present, the while loop will go into an infinite loop. So, add the extension first if not present. + if (!fileName?.endsWith(`.${mimeType.split('/')[1]}`)) { + fileName = `${fileName}.${mimeType.split('/')[1]}`; + } else if ( + fileName?.endsWith(`.${mimeType.split('/')[1]}`) && + fileName.length === `.${mimeType.split('/')[1]}`.length + ) { + fileName = `image.${mimeType.split('/')[1]}`; + } + + let match = fileName.match(/^(.+?)(\((\d+)\))?(\.[^.]+)$/); + + if (!match) return fileName; + + let c = match && !isNaN(parseInt(match[3])) ? parseInt(match[3]) : 1; + + while (attachments.some((fn) => fn === fileName)) { + fileName = `${match[1]}(${c++})${match[4]}`; + } + + return fileName; +} + export { filterOutSystemColumns, getSystemColumnsIds, @@ -106,4 +136,5 @@ export { extractRolesObj, stringifyRolesObj, getAvailableRollupForUiType, + populateUniqueFileName, };