diff --git a/__tests__/utils/app/importExports.test.ts b/__tests__/utils/app/importExports.test.ts index e189785..1593b70 100644 --- a/__tests__/utils/app/importExports.test.ts +++ b/__tests__/utils/app/importExports.test.ts @@ -1,4 +1,4 @@ -import { ExportFormatV1, ExportFormatV2 } from '@/types/export'; +import { ExportFormatV1, ExportFormatV2, ExportFormatV4 } from '@/types/export'; import { OpenAIModels, OpenAIModelID } from '@/types/openai'; import { DEFAULT_SYSTEM_PROMPT } from '@/utils/app/const'; import { it, describe, expect } from 'vitest'; @@ -8,6 +8,7 @@ import { isExportFormatV1, isExportFormatV2, isExportFormatV3, + isExportFormatV4, isLatestExportFormat, } from '@/utils/app/importExport'; @@ -47,6 +48,18 @@ describe('Export Format Functions', () => { expect(isExportFormatV3(obj)).toBe(false); }); }); + + describe('isExportFormatV4', () => { + it('should return true for v4 format', () => { + const obj = { version: 4, history: [], folders: [], prompts: [] }; + expect(isExportFormatV4(obj)).toBe(true); + }); + + it('should return false for non-v4 formats', () => { + const obj = { version: 5, history: [], folders: [], prompts: [] }; + expect(isExportFormatV4(obj)).toBe(false); + }); + }); }); describe('cleanData Functions', () => { @@ -71,7 +84,7 @@ describe('cleanData Functions', () => { const obj = cleanData(data); expect(isLatestExportFormat(obj)).toBe(true); expect(obj).toEqual({ - version: 3, + version: 4, history: [ { id: 1, @@ -92,6 +105,7 @@ describe('cleanData Functions', () => { }, ], folders: [], + prompts:[] }); }); }); @@ -125,7 +139,7 @@ describe('cleanData Functions', () => { const obj = cleanData(data); expect(isLatestExportFormat(obj)).toBe(true); expect(obj).toEqual({ - version: 3, + version: 4, history: [ { id: '1', @@ -152,7 +166,96 @@ describe('cleanData Functions', () => { type: 'chat', }, ], + prompts: [], }); }); }); + + describe('cleaning v4 data', () => { + it('should return the latest format', () => { + const data = { + version: 4, + history: [ + { + id: '1', + name: 'conversation 1', + messages: [ + { + role: 'user', + content: "what's up ?", + }, + { + role: 'assistant', + content: 'Hi', + }, + ], + model: OpenAIModels[OpenAIModelID.GPT_3_5], + prompt: DEFAULT_SYSTEM_PROMPT, + folderId: null, + }, + ], + folders: [ + { + id: '1', + name: 'folder 1', + type: 'chat', + }, + ], + prompts: [ + { + id: '1', + name: 'prompt 1', + description: '', + content: '', + model: OpenAIModels[OpenAIModelID.GPT_3_5], + folderId: null, + }, + ], + } as ExportFormatV4; + + const obj = cleanData(data); + expect(isLatestExportFormat(obj)).toBe(true); + expect(obj).toEqual({ + version: 4, + history: [ + { + id: '1', + name: 'conversation 1', + messages: [ + { + role: 'user', + content: "what's up ?", + }, + { + role: 'assistant', + content: 'Hi', + }, + ], + model: OpenAIModels[OpenAIModelID.GPT_3_5], + prompt: DEFAULT_SYSTEM_PROMPT, + folderId: null, + }, + ], + folders: [ + { + id: '1', + name: 'folder 1', + type: 'chat', + }, + ], + prompts: [ + { + id: '1', + name: 'prompt 1', + description: '', + content: '', + model: OpenAIModels[OpenAIModelID.GPT_3_5], + folderId: null, + }, + ], + + }); + }); + }); + }); diff --git a/pages/index.tsx b/pages/index.tsx index 5ec6bd7..ea205b5 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -296,11 +296,12 @@ const Home: React.FC = ({ }; const handleImportConversations = (data: SupportedExportFormats) => { - const { history, folders }: LatestExportFormat = importData(data); + const { history, folders, prompts }: LatestExportFormat = importData(data); setConversations(history); setSelectedConversation(history[history.length - 1]); setFolders(folders); + setPrompts(prompts); }; const handleSelectConversation = (conversation: Conversation) => { diff --git a/types/export.ts b/types/export.ts index 8569bda..69192d1 100644 --- a/types/export.ts +++ b/types/export.ts @@ -1,12 +1,14 @@ import { Conversation, Message } from './chat'; import { Folder } from './folder'; import { OpenAIModel } from './openai'; +import { Prompt } from './prompt'; export type SupportedExportFormats = | ExportFormatV1 | ExportFormatV2 - | ExportFormatV3; -export type LatestExportFormat = ExportFormatV3; + | ExportFormatV3 + | ExportFormatV4; +export type LatestExportFormat = ExportFormatV4; //////////////////////////////////////////////////////////////////////////////////////////// interface ConversationV1 { @@ -34,3 +36,10 @@ export interface ExportFormatV3 { history: Conversation[]; folders: Folder[]; } + +export interface ExportFormatV4 { + version: 4; + history: Conversation[]; + folders: Folder[]; + prompts: Prompt[] +} diff --git a/utils/app/importExport.ts b/utils/app/importExport.ts index 2cc967e..69e8e72 100644 --- a/utils/app/importExport.ts +++ b/utils/app/importExport.ts @@ -2,6 +2,7 @@ import { ExportFormatV1, ExportFormatV2, ExportFormatV3, + ExportFormatV4, LatestExportFormat, SupportedExportFormats, } from '@/types/export'; @@ -19,33 +20,44 @@ export function isExportFormatV3(obj: any): obj is ExportFormatV3 { return obj.version === 3; } -export const isLatestExportFormat = isExportFormatV3; +export function isExportFormatV4(obj: any): obj is ExportFormatV4 { + return obj.version === 4; +} + +export const isLatestExportFormat = isExportFormatV4; export function cleanData(data: SupportedExportFormats): LatestExportFormat { if (isExportFormatV1(data)) { return { - version: 3, + version: 4, history: cleanConversationHistory(data), folders: [], + prompts: [], }; } if (isExportFormatV2(data)) { return { - version: 3, + version: 4, history: cleanConversationHistory(data.history || []), folders: (data.folders || []).map((chatFolder) => ({ id: chatFolder.id.toString(), name: chatFolder.name, type: 'chat', })), + prompts: [], }; } - if (isExportFormatV3(data)) { + if (isExportFormatV3(data)) { + return {...data, version: 4, prompts: []}; + } + + if(isExportFormatV4(data)){ return data; } + throw new Error('Unsupported data format'); } @@ -59,6 +71,7 @@ function currentDate() { export const exportData = () => { let history = localStorage.getItem('conversationHistory'); let folders = localStorage.getItem('folders'); + let prompts = localStorage.getItem('prompts'); if (history) { history = JSON.parse(history); @@ -68,10 +81,15 @@ export const exportData = () => { folders = JSON.parse(folders); } + if(prompts){ + prompts = JSON.parse(prompts); + } + const data = { - version: 3, + version: 4, history: history || [], folders: folders || [], + prompts: prompts || [], } as LatestExportFormat; const blob = new Blob([JSON.stringify(data, null, 2)], { @@ -92,15 +110,17 @@ export const importData = ( data: SupportedExportFormats, ): LatestExportFormat => { const cleanedData = cleanData(data); + const { history,folders, prompts } = cleanedData; - const conversations = cleanedData.history; + const conversations = history; localStorage.setItem('conversationHistory', JSON.stringify(conversations)); localStorage.setItem( 'selectedConversation', JSON.stringify(conversations[conversations.length - 1]), ); - localStorage.setItem('folders', JSON.stringify(cleanedData.folders)); + localStorage.setItem('folders', JSON.stringify(folders)); + localStorage.setItem('prompts', JSON.stringify(prompts)); return cleanedData; };