From 49cac30d64d0cef816e9465e2dc8f95716433da4 Mon Sep 17 00:00:00 2001 From: xesrc <7753089+xesrc@users.noreply.github.com> Date: Sun, 7 May 2023 20:02:51 +0800 Subject: [PATCH] support for conversation export and import --- components/NavigationDrawer.vue | 312 ++++++++++++++++++++++---------- lang/en-US.json | 2 + lang/zh-CN.json | 2 + 3 files changed, 222 insertions(+), 94 deletions(-) diff --git a/components/NavigationDrawer.vue b/components/NavigationDrawer.vue index 38b8d6a..06b3a62 100644 --- a/components/NavigationDrawer.vue +++ b/components/NavigationDrawer.vue @@ -30,8 +30,8 @@ const setLang = (lang) => { const conversations = useConversations() -const editingConversation = ref(null) -const deletingConversationIndex = ref(null) +const editingConversation = ref(false) +const deletingConversationIndex = ref(false) const editConversation = (index) => { editingConversation.value = conversations.value[index] @@ -46,9 +46,11 @@ const updateConversation = async (index) => { }) }) if (!error.value) { + editingConversation.value.updating = false conversations.value[index] = editingConversation.value } - editingConversation.value = null + conversations.value[index].updating = false + editingConversation.value = false } const deleteConversation = async (index) => { @@ -66,6 +68,91 @@ const deleteConversation = async (index) => { } } +const snackbar = ref(false) +const snackbarText = ref('') +const showSnackbar = (text) => { + snackbarText.value = text + snackbar.value = true +} + +const loadMessage = async (conversation_id) => { + const { data, error } = await useAuthFetch(`/api/chat/messages/?conversationId=${conversation_id}`) + if (!error.value) { + return data.value + } + return error.value +} + +const exportConversation = async (index) => { + let conversation = conversations.value[index] + let data = {} + data.conversation_topic = conversation.topic + data.messages = [] + let messages = await loadMessage(conversation.id) + for (let message of messages) { + let msg = {} + msg.role = message.is_bot ? "assistant" : "user" + msg.content = message.message + data.messages.push(msg) + } + let file_content = JSON.stringify(data) + let file_name = `${conversation.topic}_${new Date()}`.replace(/[\/\\:*?"<>]/g, "_") + const element = document.createElement('a'); + element.setAttribute( + "href", + "data:text/plain;charset=utf-8," + encodeURIComponent(file_content), + ); + element.setAttribute("download", file_name); + element.style.display = "none"; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); +} + +const openImportFileChooser = async () => { + let input_element = document.getElementById("import_conversation_input") + input_element.click() +} + +const importConversation = async () => { + let input_element = document.getElementById("import_conversation_input") + let fileHandles = input_element.files + let imports = [] + const reader = new FileReader() + for (let handle of fileHandles) { + let content = await new Promise((resolve, reject) => { + reader.readAsText(handle) + reader.onload = () => resolve(reader.result); + reader.onerror = eror => reject(error); + }) + let json = JSON.parse(content) + imports.push(json) + } + let new_conversation_ids = [] + try { + const { data, error } = await useAuthFetch('/api/upload_conversations/', { + method: 'POST', + headers: { + 'accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + imports: imports, + }), + }) + if (!error.value) { + new_conversation_ids = data.value + loadConversations() + } else { + console.log(err) + showSnackbar(err.message) + } + } catch (err) { + console.log(err.message) + showSnackbar(err.message) + } +} + const clearConversations = async () => { deletingConversations.value = true const { data, error } = await useAuthFetch(`/api/chat/conversations/delete_all`, { @@ -218,6 +305,13 @@ const drawer = useDrawer() @click.prevent="deleteConversation(cIdx)" > + + @@ -227,104 +321,134 @@ const drawer = useDrawer() + + {{ snackbarText }} + + +