diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 014b8436e..d3e764143 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -53,7 +53,8 @@ getPromptVariables, processDetails, removeAllDetails, - getCodeBlockContents + getCodeBlockContents, + isYoutubeUrl } from '$lib/utils'; import { AudioQueue } from '$lib/utils/audio'; @@ -773,69 +774,61 @@ } }; - const uploadWeb = async (url) => { - console.log(url); - - const fileItem = { - type: 'text', - name: url, - collection_name: '', - status: 'uploading', - url: url, - error: '' - }; - - try { - files = [...files, fileItem]; - const res = await processWeb(localStorage.token, '', url); - - if (res) { - fileItem.status = 'uploaded'; - fileItem.collection_name = res.collection_name; - fileItem.file = { - ...res.file, - ...fileItem.file - }; - - files = files; - } - } catch (e) { - // Remove the failed doc from the files array - files = files.filter((f) => f.name !== url); - toast.error(JSON.stringify(e)); + const uploadWeb = async (urls) => { + if (!Array.isArray(urls)) { + urls = [urls]; } - }; - const uploadYoutubeTranscription = async (url) => { - console.log(url); + // deduplicate URLs + urls = [...new Set(urls)]; - const fileItem = { + // Create file items first + const fileItems = urls.map((url) => ({ type: 'text', name: url, collection_name: '', status: 'uploading', context: 'full', - url: url, + url, error: '' - }; + })); - try { - files = [...files, fileItem]; - const res = await processYoutubeVideo(localStorage.token, url); + // Display all items at once + files = [...files, ...fileItems]; - if (res) { - fileItem.status = 'uploaded'; - fileItem.collection_name = res.collection_name; - fileItem.file = { - ...res.file, - ...fileItem.file - }; - files = files; + // Process sequentially (NOT parallel) + for (const fileItem of fileItems) { + try { + const res = isYoutubeUrl(fileItem.url) + ? await processYoutubeVideo(localStorage.token, fileItem.url) + : await processWeb(localStorage.token, '', fileItem.url); + + if (res) { + fileItem.status = 'uploaded'; + fileItem.collection_name = res.collection_name; + fileItem.file = { + ...res.file, + ...fileItem.file + }; + } + } catch (e) { + fileItem.status = 'error'; + fileItem.error = String(e); + toast.error(`${e}`); } - } catch (e) { - // Remove the failed doc from the files array - files = files.filter((f) => f.name !== url); - toast.error(`${e}`); + + // Force UI reactivity after each file finishes + files = [...files]; + } + }; + + const onUpload = async (event) => { + const { type, data } = event; + + if (type === 'google-drive') { + await uploadGoogleDriveFile(data); + } else if (type === 'web') { + await uploadWeb(data); } }; @@ -1010,9 +1003,7 @@ params = {}; if ($page.url.searchParams.get('youtube')) { - uploadYoutubeTranscription( - `https://www.youtube.com/watch?v=${$page.url.searchParams.get('youtube')}` - ); + await uploadWeb(`https://www.youtube.com/watch?v=${$page.url.searchParams.get('youtube')}`); } if ($page.url.searchParams.get('load-url')) { @@ -2532,22 +2523,12 @@ {generating} {stopResponse} {createMessagePair} + {onUpload} onChange={(data) => { if (!$temporaryChatEnabled) { saveDraft(data, $chatId); } }} - on:upload={async (e) => { - const { type, data } = e.detail; - - if (type === 'web') { - await uploadWeb(data); - } else if (type === 'youtube') { - await uploadYoutubeTranscription(data); - } else if (type === 'google-drive') { - await uploadGoogleDriveFile(data); - } - }} on:submit={async (e) => { clearDraft(); if (e.detail || files.length > 0) { @@ -2584,20 +2565,12 @@ {stopResponse} {createMessagePair} {onSelect} + {onUpload} onChange={(data) => { if (!$temporaryChatEnabled) { saveDraft(data); } }} - on:upload={async (e) => { - const { type, data } = e.detail; - - if (type === 'web') { - await uploadWeb(data); - } else if (type === 'youtube') { - await uploadYoutubeTranscription(data); - } - }} on:submit={async (e) => { clearDraft(); if (e.detail || files.length > 0) { diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index ef0bfe089..ae7a8e105 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -94,6 +94,7 @@ const i18n = getContext('i18n'); export let onChange: Function = () => {}; + export let createMessagePair: Function; export let stopResponse: Function; @@ -848,7 +849,7 @@ } ]; } else { - dispatch('upload', e); + onUpload(e); } } }) @@ -883,7 +884,7 @@ } ]; } else { - dispatch('upload', e); + onUpload(e); } } }) @@ -918,7 +919,7 @@ } ]; } else { - dispatch('upload', e); + onUpload(e); } } }) @@ -1487,9 +1488,7 @@ console.error('OneDrive Error:', error); } }} - onUpload={async (e) => { - dispatch('upload', e); - }} + {onUpload} onClose={async () => { await tick(); diff --git a/src/lib/components/chat/MessageInput/AttachWebpageModal.svelte b/src/lib/components/chat/MessageInput/AttachWebpageModal.svelte index ae6f63ef2..52640969f 100644 --- a/src/lib/components/chat/MessageInput/AttachWebpageModal.svelte +++ b/src/lib/components/chat/MessageInput/AttachWebpageModal.svelte @@ -7,7 +7,7 @@ import Modal from '$lib/components/common/Modal.svelte'; import XMark from '$lib/components/icons/XMark.svelte'; - import { isValidHttpUrl, isYoutubeUrl } from '$lib/utils'; + import { isValidHttpUrl } from '$lib/utils'; export let show = false; export let onSubmit: (e) => void; @@ -15,17 +15,20 @@ let url = ''; const submitHandler = () => { - if (isValidHttpUrl(url)) { - onSubmit({ - type: isYoutubeUrl(url) ? 'youtube' : 'web', - data: url - }); + const urls = url + .split('\n') + .map((u) => u.trim()) + .filter((u) => u !== '') + .filter((u) => isValidHttpUrl(u)); - show = false; - url = ''; - } else { + if (urls.length === 0) { toast.error($i18n.t('Please enter a valid URL.')); + return; } + + onSubmit({ type: 'web', data: urls }); + show = false; + url = ''; }; @@ -57,15 +60,16 @@ {$i18n.t('Webpage URLs')} - { if (isValidHttpUrl(query)) { onSelect({ - type: 'youtube', + type: 'web', data: query }); } else { diff --git a/src/lib/components/chat/Placeholder.svelte b/src/lib/components/chat/Placeholder.svelte index d0b3a19a7..fc898b45d 100644 --- a/src/lib/components/chat/Placeholder.svelte +++ b/src/lib/components/chat/Placeholder.svelte @@ -54,6 +54,7 @@ export let codeInterpreterEnabled = false; export let webSearchEnabled = false; + export let onUpload: Function = (e) => {}; export let onSelect = (e) => {}; export let onChange = (e) => {}; @@ -216,9 +217,7 @@ {createMessagePair} placeholder={$i18n.t('How can I help you today?')} {onChange} - on:upload={(e) => { - dispatch('upload', e.detail); - }} + {onUpload} on:submit={(e) => { dispatch('submit', e.detail); }} diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte index ce5120945..67bfb9d09 100644 --- a/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte +++ b/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte @@ -51,13 +51,16 @@ import FilesOverlay from '$lib/components/chat/MessageInput/FilesOverlay.svelte'; import DropdownOptions from '$lib/components/common/DropdownOptions.svelte'; import Pagination from '$lib/components/common/Pagination.svelte'; + import AttachWebpageModal from '$lib/components/chat/MessageInput/AttachWebpageModal.svelte'; let largeScreen = true; let pane; let showSidepanel = true; + let showAddWebpageModal = false; let showAddTextContentModal = false; + let showSyncConfirmModal = false; let showAccessControlModal = false; @@ -696,6 +699,13 @@ }} /> + { + console.log(data); + }} +/> + { @@ -829,6 +839,8 @@ onUpload={(data) => { if (data.type === 'directory') { uploadDirectoryHandler(); + } else if (data.type === 'web') { + showAddWebpageModal = true; } else if (data.type === 'text') { showAddTextContentModal = true; } else { diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase/AddContentMenu.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase/AddContentMenu.svelte index 44000de45..4944e4ffb 100644 --- a/src/lib/components/workspace/Knowledge/KnowledgeBase/AddContentMenu.svelte +++ b/src/lib/components/workspace/Knowledge/KnowledgeBase/AddContentMenu.svelte @@ -10,6 +10,7 @@ import BarsArrowUp from '$lib/components/icons/BarsArrowUp.svelte'; import FolderOpen from '$lib/components/icons/FolderOpen.svelte'; import ArrowPath from '$lib/components/icons/ArrowPath.svelte'; + import GlobeAlt from '$lib/components/icons/GlobeAlt.svelte'; const i18n = getContext('i18n'); @@ -96,6 +97,16 @@ + { + onUpload({ type: 'web' }); + }} + > + +
{$i18n.t('Add webpage')}
+
+ {