diff --git a/apps/chat/src/components/Common/FullPageLoader.tsx b/apps/chat/src/components/Common/FullPageLoader.tsx index 8b611dc605..1d3b2c520f 100644 --- a/apps/chat/src/components/Common/FullPageLoader.tsx +++ b/apps/chat/src/components/Common/FullPageLoader.tsx @@ -30,17 +30,19 @@ export const FullPageLoader = ({ hideClose={hideClose} dataQa={dataQa} portalId={portalId} - containerClassName="bg-transparent items-center gap-4 flex flex-col" + containerClassName="bg-transparent" > - +
+ -

{loaderLabel}

- +

{loaderLabel}

+ +
); }; diff --git a/apps/chat/src/store/import-export/importExport.epics.ts b/apps/chat/src/store/import-export/importExport.epics.ts index f0e7f93fbb..8834381f27 100644 --- a/apps/chat/src/store/import-export/importExport.epics.ts +++ b/apps/chat/src/store/import-export/importExport.epics.ts @@ -25,6 +25,7 @@ import { exportConversation, exportConversations, importConversations, + updateAttachment, } from '@/src/utils/app/import-export'; import { compressConversationInZip, @@ -33,7 +34,7 @@ import { importZippedHistory, } from '@/src/utils/app/zip-import-export'; -import { Conversation, Message } from '@/src/types/chat'; +import { Conversation, Message, Stage } from '@/src/types/chat'; import { LatestExportFormat } from '@/src/types/importExport'; import { AppEpic } from '@/src/types/store'; @@ -266,6 +267,7 @@ const uploadConversationAttachmentsEpic: AppEpic = (action$, state$) => }), ); } + formData.append('attachment', attachment.fileContent, attachment.name); const relativePath = `imports/${conversation.id}/${attachment.relativePath}`; return DataService.sendFile( @@ -373,50 +375,30 @@ const uploadAllAttachmentsSuccessEpic: AppEpic = (action$, state$) => } const newAttachments = message.custom_content.attachments.map( - (oldAttachment) => { - if (!oldAttachment.url) { - return oldAttachment; - } - - const regExpForOldAttachmentId = /^files\/\w*\//; - const indexAfterSplit = 1; - const oldAttachmentId = decodeURI(oldAttachment.url).split( - regExpForOldAttachmentId, - )[indexAfterSplit]; - - const newAttachmentFile = uploadedAttachments.find( - (newAttachment) => { - if (!newAttachment.id) { - return; - } - const regExpForNewAttachmentId = /^imports\/[\w-]*\//; - const newAttachmentId = newAttachment.id.split( - regExpForNewAttachmentId, - )[indexAfterSplit]; - return newAttachmentId === oldAttachmentId; - }, - ); + (oldAttachment) => + updateAttachment({ oldAttachment, uploadedAttachments }), + ); - if ( - !newAttachmentFile || - !newAttachmentFile.contentType || - !newAttachmentFile.name - ) { - return oldAttachment; + const newStages: Stage[] | undefined = + message.custom_content.stages && + message.custom_content.stages.map((stage) => { + if (!stage.attachments) { + return stage; } - + const newStageAttachments = stage.attachments.map( + (oldAttachment) => + updateAttachment({ oldAttachment, uploadedAttachments }), + ); return { - ...oldAttachment, - url: encodeURI( - `${newAttachmentFile.absolutePath}/${newAttachmentFile.name}`, - ), + ...stage, + attachments: newStageAttachments, }; - }, - ); + }); const newCustomContent: Message['custom_content'] = { ...message.custom_content, attachments: newAttachments, + stages: newStages, }; return { ...message, diff --git a/apps/chat/src/utils/app/import-export.ts b/apps/chat/src/utils/app/import-export.ts index 9b96990d3f..9eb35a3d30 100644 --- a/apps/chat/src/utils/app/import-export.ts +++ b/apps/chat/src/utils/app/import-export.ts @@ -1,4 +1,5 @@ -import { Conversation } from '@/src/types/chat'; +import { Attachment, Conversation } from '@/src/types/chat'; +import { DialFile } from '@/src/types/files'; import { FolderInterface, FolderType } from '@/src/types/folder'; import { ExportConversationsFormatV4, @@ -285,3 +286,92 @@ export const importPrompts = ( return { prompts: newPrompts, folders: newFolders, isError: false }; }; + +export const getAttachmentId = ({ + url, + attachmentIdIndex, +}: { + url: string; + attachmentIdIndex: number; +}) => { + const regExpForAttachmentId = /^files\/\w*\//; + + const attachmentId = decodeURI(url).split(regExpForAttachmentId)[ + attachmentIdIndex + ]; + + return attachmentId; +}; + +const getNewAttachmentFileFromUploaded = ({ + uploadedAttachments, + oldAttachmentId, + attachmentIdIndex, +}: { + uploadedAttachments: Partial[]; + oldAttachmentId: string; + attachmentIdIndex: number; +}) => + uploadedAttachments.find((newAttachment) => { + if (!newAttachment.id) { + return; + } + const regExpForNewAttachmentId = /^imports\/[\w-]*\//; + + const newAttachmentId = newAttachment.id.split(regExpForNewAttachmentId)[ + attachmentIdIndex + ]; + return ( + newAttachmentId === oldAttachmentId || + oldAttachmentId.includes(newAttachmentId) + ); + }); + +export const updateAttachment = ({ + oldAttachment, + uploadedAttachments, +}: { + oldAttachment: Attachment; + uploadedAttachments: Partial[]; +}) => { + const oldAttachmentUrl = oldAttachment.url || oldAttachment.reference_url; + + if (!oldAttachmentUrl) { + return oldAttachment; + } + + const attachmentIdIndex = 1; + + const oldAttachmentId = getAttachmentId({ + url: oldAttachmentUrl, + attachmentIdIndex, + }); + + const newAttachmentFile = getNewAttachmentFileFromUploaded({ + uploadedAttachments, + oldAttachmentId, + attachmentIdIndex, + }); + + if (!newAttachmentFile || !newAttachmentFile.name) { + return oldAttachment; + } + + const newAttachmentUrl = + oldAttachment.url && + encodeURI(`${newAttachmentFile.absolutePath}/${newAttachmentFile.name}`); + + const lastSlashIndex = oldAttachmentId.lastIndexOf('/'); + const oldAttachmentNameInPath = oldAttachmentId.slice(lastSlashIndex + 1); + + const newReferenceUrl = + oldAttachment.reference_url && + encodeURI(`${newAttachmentFile.absolutePath}/${oldAttachmentNameInPath}`); + + const updatedAttachment: Attachment = { + ...oldAttachment, + url: newAttachmentUrl, + reference_url: newReferenceUrl, + }; + return updatedAttachment; +}; diff --git a/apps/chat/src/utils/app/zip-import-export.ts b/apps/chat/src/utils/app/zip-import-export.ts index a7c8300f60..0acf183478 100644 --- a/apps/chat/src/utils/app/zip-import-export.ts +++ b/apps/chat/src/utils/app/zip-import-export.ts @@ -8,6 +8,7 @@ import { constructPath, triggerDownload } from './file'; import { prepareConversationsForExport } from './import-export'; import JSZip from 'jszip'; +import { contentType } from 'mime-types'; interface GetZippedFile { files: DialFile[]; @@ -114,11 +115,6 @@ export const getUnZipAttachments = async ({ if (!file) { return; } - const fileContent = await file.async('blob'); - - if (!fileContent) { - return; - } const firstSlashIndex = getFirstSlashIndex(relativePath); const lastSlashIndex = zipEntry.name.lastIndexOf('/'); @@ -129,6 +125,17 @@ export const getUnZipAttachments = async ({ lastSlashIndex, ); const fileId = relativePath.slice(firstSlashIndex + substringLength); + const fileContentBlob = await file.async('blob'); + + const fileContent = fileContentBlob.type.length + ? fileContentBlob + : new File([fileContentBlob], fileName, { + type: contentType(fileName) || 'application/octet-stream', + }); + + if (!fileContent) { + return; + } const attachmentToUpload = { fileContent,