diff --git a/CHANGELOG.md b/CHANGELOG.md index 32679bd42..7b150de25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.105] - 2024-02-25 + +### Added + +- **📄 Document Selection**: Now you can select and delete multiple documents at once for easier management. + +### Changed + +- **🏷️ Document Pre-tagging**: Simply click the "+" button at the top, enter tag names in the popup window, or select from a list of existing tags. Then, upload files with the added tags for streamlined organization. + ## [0.1.104] - 2024-02-25 ### Added diff --git a/package.json b/package.json index 4a33ec43a..dd212e7dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-webui", - "version": "0.1.104", + "version": "0.1.105", "private": true, "scripts": { "dev": "vite dev --host", diff --git a/src/lib/apis/documents/index.ts b/src/lib/apis/documents/index.ts index 2f7fb2b94..21e0a2643 100644 --- a/src/lib/apis/documents/index.ts +++ b/src/lib/apis/documents/index.ts @@ -5,7 +5,8 @@ export const createNewDoc = async ( collection_name: string, filename: string, name: string, - title: string + title: string, + content: object | null = null ) => { let error = null; @@ -20,7 +21,8 @@ export const createNewDoc = async ( collection_name: collection_name, filename: filename, name: name, - title: title + title: title, + ...(content ? { content: JSON.stringify(content) } : {}) }) }) .then(async (res) => { diff --git a/src/lib/apis/openai/index.ts b/src/lib/apis/openai/index.ts index 414455813..3a629eb31 100644 --- a/src/lib/apis/openai/index.ts +++ b/src/lib/apis/openai/index.ts @@ -150,7 +150,6 @@ export const getOpenAIModels = async (token: string = '') => { return res.json(); }) .catch((err) => { - console.log(err); error = `OpenAI: ${err?.error?.message ?? 'Network Problem'}`; return []; }); diff --git a/src/lib/components/common/Checkbox.svelte b/src/lib/components/common/Checkbox.svelte new file mode 100644 index 000000000..f69a58401 --- /dev/null +++ b/src/lib/components/common/Checkbox.svelte @@ -0,0 +1,70 @@ + + + diff --git a/src/lib/components/documents/AddDocModal.svelte b/src/lib/components/documents/AddDocModal.svelte new file mode 100644 index 000000000..bf24f9c6f --- /dev/null +++ b/src/lib/components/documents/AddDocModal.svelte @@ -0,0 +1,188 @@ + + + +
+
+
Add Docs
+ +
+
+ +
+
+
{ + submitHandler(); + }} + > +
+ + + +
+ +
+
+
Tags
+ + +
+
+ +
+ +
+
+
+
+
+
+ + diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte index f2f4d69d2..7d424be47 100644 --- a/src/routes/(app)/+page.svelte +++ b/src/routes/(app)/+page.svelte @@ -104,13 +104,8 @@ await cancelChatCompletion(localStorage.token, currentRequestId); currentRequestId = null; } - window.history.replaceState(history.state, '', `/`); - - console.log('initNewChat'); - await chatId.set(''); - console.log($chatId); autoScroll = true; @@ -121,8 +116,6 @@ currentId: null }; - console.log($config); - if ($page.url.searchParams.get('models')) { selectedModels = $page.url.searchParams.get('models')?.split(','); } else if ($settings?.models) { diff --git a/src/routes/(app)/documents/+page.svelte b/src/routes/(app)/documents/+page.svelte index b2d289413..79fe691b8 100644 --- a/src/routes/(app)/documents/+page.svelte +++ b/src/routes/(app)/documents/+page.svelte @@ -11,9 +11,12 @@ import { uploadDocToVectorDB } from '$lib/apis/rag'; import { transformFileName } from '$lib/utils'; + import Checkbox from '$lib/components/common/Checkbox.svelte'; + import EditDocModal from '$lib/components/documents/EditDocModal.svelte'; import AddFilesPlaceholder from '$lib/components/AddFilesPlaceholder.svelte'; import SettingsModal from '$lib/components/documents/SettingsModal.svelte'; + import AddDocModal from '$lib/components/documents/AddDocModal.svelte'; let importFiles = ''; let inputFiles = ''; @@ -22,6 +25,7 @@ let tags = []; let showSettingsModal = false; + let showAddDocModal = false; let showEditDocModal = false; let selectedDoc; let selectedTag = ''; @@ -33,6 +37,16 @@ await documents.set(await getDocs(localStorage.token)); }; + const deleteDocs = async (docs) => { + const res = await Promise.all( + docs.map(async (doc) => { + return await deleteDocByName(localStorage.token, doc.name); + }) + ); + + await documents.set(await getDocs(localStorage.token)); + }; + const uploadDoc = async (file) => { const res = await uploadDocToVectorDB(localStorage.token, '', file).catch((error) => { toast.error(error); @@ -123,6 +137,15 @@ dropZone?.removeEventListener('dragleave', onDragLeave); }; }); + + let filteredDocs; + + $: filteredDocs = $documents.filter( + (doc) => + (selectedTag === '' || + (doc?.content?.tags ?? []).map((tag) => tag.name).includes(selectedTag)) && + (query === '' || doc.name.includes(query)) + ); {#if dragged} @@ -150,36 +173,7 @@ {/key} - { - if (inputFiles && inputFiles.length > 0) { - for (const file of inputFiles) { - console.log(file, file.name.split('.').at(-1)); - if ( - SUPPORTED_FILE_TYPE.includes(file['type']) || - SUPPORTED_FILE_EXTENSIONS.includes(file.name.split('.').at(-1)) - ) { - uploadDoc(file); - } else { - toast.error( - `Unknown File Type '${file['type']}', but accepting and treating as plain text` - ); - uploadDoc(file); - } - } - - inputFiles = null; - e.target.value = ''; - } else { - toast.error(`File not found.`); - } - }} -/> + @@ -247,7 +241,7 @@ - {#each tags as tag} +
+ doc?.selected === 'checked').length === + filteredDocs.length + ? 'checked' + : 'unchecked'} + indeterminate={filteredDocs.filter((doc) => doc?.selected === 'checked').length > 0 && + filteredDocs.filter((doc) => doc?.selected === 'checked').length !== + filteredDocs.length} + on:change={(e) => { + if (e.detail === 'checked') { + filteredDocs = filteredDocs.map((doc) => ({ ...doc, selected: 'checked' })); + } else if (e.detail === 'unchecked') { + filteredDocs = filteredDocs.map((doc) => ({ ...doc, selected: 'unchecked' })); + } + }} + /> +
+ + {#if filteredDocs.filter((doc) => doc?.selected === 'checked').length === 0} - {/each} + + {#each tags as tag} + + {/each} + {:else} +
+
+ {filteredDocs.filter((doc) => doc?.selected === 'checked').length} Selected +
+ +
+ + + +
+
+ {/if} {/if}
- {#each $documents.filter((doc) => (selectedTag === '' || (doc?.content?.tags ?? []) - .map((tag) => tag.name) - .includes(selectedTag)) && (query === '' || doc.name.includes(query))) as doc} -
{ + if (doc?.selected === 'checked') { + doc.selected = 'unchecked'; + } else { + doc.selected = 'checked'; + } + }} > +
+ +
@@ -387,9 +439,10 @@
-
+ {/each}