diff --git a/backend/open_webui/test/apps/webui/routers/test_documents.py b/backend/open_webui/test/apps/webui/routers/test_documents.py
deleted file mode 100644
index 4d30b35e4..000000000
--- a/backend/open_webui/test/apps/webui/routers/test_documents.py
+++ /dev/null
@@ -1,105 +0,0 @@
-from test.util.abstract_integration_test import AbstractPostgresTest
-from test.util.mock_user import mock_webui_user
-
-
-class TestDocuments(AbstractPostgresTest):
- BASE_PATH = "/api/v1/documents"
-
- def setup_class(cls):
- super().setup_class()
- from open_webui.apps.webui.models.documents import Documents
-
- cls.documents = Documents
-
- def test_documents(self):
- # Empty database
- assert len(self.documents.get_docs()) == 0
- with mock_webui_user(id="2"):
- response = self.fast_api_client.get(self.create_url("/"))
- assert response.status_code == 200
- assert len(response.json()) == 0
-
- # Create a new document
- with mock_webui_user(id="2"):
- response = self.fast_api_client.post(
- self.create_url("/create"),
- json={
- "name": "doc_name",
- "title": "doc title",
- "collection_name": "custom collection",
- "filename": "doc_name.pdf",
- "content": "",
- },
- )
- assert response.status_code == 200
- assert response.json()["name"] == "doc_name"
- assert len(self.documents.get_docs()) == 1
-
- # Get the document
- with mock_webui_user(id="2"):
- response = self.fast_api_client.get(self.create_url("/doc?name=doc_name"))
- assert response.status_code == 200
- data = response.json()
- assert data["collection_name"] == "custom collection"
- assert data["name"] == "doc_name"
- assert data["title"] == "doc title"
- assert data["filename"] == "doc_name.pdf"
- assert data["content"] == {}
-
- # Create another document
- with mock_webui_user(id="2"):
- response = self.fast_api_client.post(
- self.create_url("/create"),
- json={
- "name": "doc_name 2",
- "title": "doc title 2",
- "collection_name": "custom collection 2",
- "filename": "doc_name2.pdf",
- "content": "",
- },
- )
- assert response.status_code == 200
- assert response.json()["name"] == "doc_name 2"
- assert len(self.documents.get_docs()) == 2
-
- # Get all documents
- with mock_webui_user(id="2"):
- response = self.fast_api_client.get(self.create_url("/"))
- assert response.status_code == 200
- assert len(response.json()) == 2
-
- # Update the first document
- with mock_webui_user(id="2"):
- response = self.fast_api_client.post(
- self.create_url("/doc/update?name=doc_name"),
- json={"name": "doc_name rework", "title": "updated title"},
- )
- assert response.status_code == 200
- data = response.json()
- assert data["name"] == "doc_name rework"
- assert data["title"] == "updated title"
-
- # Tag the first document
- with mock_webui_user(id="2"):
- response = self.fast_api_client.post(
- self.create_url("/doc/tags"),
- json={
- "name": "doc_name rework",
- "tags": [{"name": "testing-tag"}, {"name": "another-tag"}],
- },
- )
- assert response.status_code == 200
- data = response.json()
- assert data["name"] == "doc_name rework"
- assert data["content"] == {
- "tags": [{"name": "testing-tag"}, {"name": "another-tag"}]
- }
- assert len(self.documents.get_docs()) == 2
-
- # Delete the first document
- with mock_webui_user(id="2"):
- response = self.fast_api_client.delete(
- self.create_url("/doc/delete?name=doc_name rework")
- )
- assert response.status_code == 200
- assert len(self.documents.get_docs()) == 1
diff --git a/cypress/e2e/documents.cy.ts b/cypress/e2e/documents.cy.ts
index 6ca14980d..b14b1de20 100644
--- a/cypress/e2e/documents.cy.ts
+++ b/cypress/e2e/documents.cy.ts
@@ -1,46 +1,2 @@
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
///
-
-describe('Documents', () => {
- const timestamp = Date.now();
-
- before(() => {
- cy.uploadTestDocument(timestamp);
- });
-
- after(() => {
- cy.deleteTestDocument(timestamp);
- });
-
- context('Admin', () => {
- beforeEach(() => {
- // Login as the admin user
- cy.loginAdmin();
- // Visit the home page
- cy.visit('/workspace/documents');
- cy.get('button').contains('#cypress-test').click();
- });
-
- it('can see documents', () => {
- cy.get('div').contains(`document-test-initial-${timestamp}.txt`).should('have.length', 1);
- });
-
- it('can see edit button', () => {
- cy.get('div')
- .contains(`document-test-initial-${timestamp}.txt`)
- .get("button[aria-label='Edit Doc']")
- .should('exist');
- });
-
- it('can see delete button', () => {
- cy.get('div')
- .contains(`document-test-initial-${timestamp}.txt`)
- .get("button[aria-label='Delete Doc']")
- .should('exist');
- });
-
- it('can see upload button', () => {
- cy.get("button[aria-label='Add Docs']").should('exist');
- });
- });
-});
diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts
index 984788733..0b94c4787 100644
--- a/cypress/support/e2e.ts
+++ b/cypress/support/e2e.ts
@@ -73,50 +73,6 @@ Cypress.Commands.add('register', (name, email, password) => register(name, email
Cypress.Commands.add('registerAdmin', () => registerAdmin());
Cypress.Commands.add('loginAdmin', () => loginAdmin());
-Cypress.Commands.add('uploadTestDocument', (suffix: any) => {
- // Login as admin
- cy.loginAdmin();
- // upload example document
- cy.visit('/workspace/documents');
- // Create a document
- cy.get("button[aria-label='Add Docs']").click();
- cy.readFile('cypress/data/example-doc.txt').then((text) => {
- // select file
- cy.get('#upload-doc-input').selectFile(
- {
- contents: Cypress.Buffer.from(text + Date.now()),
- fileName: `document-test-initial-${suffix}.txt`,
- mimeType: 'text/plain',
- lastModified: Date.now()
- },
- {
- force: true
- }
- );
- // open tag input
- cy.get("button[aria-label='Add Tag']").click();
- cy.get("input[placeholder='Add a tag']").type('cypress-test');
- cy.get("button[aria-label='Save Tag']").click();
-
- // submit to upload
- cy.get("button[type='submit']").click();
-
- // wait for upload to finish
- cy.get('button').contains('#cypress-test').should('exist');
- cy.get('div').contains(`document-test-initial-${suffix}.txt`).should('exist');
- });
-});
-
-Cypress.Commands.add('deleteTestDocument', (suffix: any) => {
- cy.loginAdmin();
- cy.visit('/workspace/documents');
- // clean up uploaded documents
- cy.get('div')
- .contains(`document-test-initial-${suffix}.txt`)
- .find("button[aria-label='Delete Doc']")
- .click();
-});
-
before(() => {
cy.registerAdmin();
});
diff --git a/src/lib/apis/documents/index.ts b/src/lib/apis/documents/index.ts
deleted file mode 100644
index 9d42feb19..000000000
--- a/src/lib/apis/documents/index.ts
+++ /dev/null
@@ -1,232 +0,0 @@
-import { WEBUI_API_BASE_URL } from '$lib/constants';
-
-export const createNewDoc = async (
- token: string,
- collection_name: string,
- filename: string,
- name: string,
- title: string,
- content: object | null = null
-) => {
- let error = null;
-
- const res = await fetch(`${WEBUI_API_BASE_URL}/documents/create`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- collection_name: collection_name,
- filename: filename,
- name: name,
- title: title,
- ...(content ? { content: JSON.stringify(content) } : {})
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .catch((err) => {
- error = err.detail;
- console.log(err);
- return null;
- });
-
- if (error) {
- throw error;
- }
-
- return res;
-};
-
-export const getDocs = async (token: string = '') => {
- let error = null;
-
- const res = await fetch(`${WEBUI_API_BASE_URL}/documents/`, {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- authorization: `Bearer ${token}`
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .then((json) => {
- return json;
- })
- .catch((err) => {
- error = err.detail;
- console.log(err);
- return null;
- });
-
- if (error) {
- throw error;
- }
-
- return res;
-};
-
-export const getDocByName = async (token: string, name: string) => {
- let error = null;
-
- const searchParams = new URLSearchParams();
- searchParams.append('name', name);
-
- const res = await fetch(`${WEBUI_API_BASE_URL}/documents/docs?${searchParams.toString()}`, {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- authorization: `Bearer ${token}`
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .then((json) => {
- return json;
- })
- .catch((err) => {
- error = err.detail;
-
- console.log(err);
- return null;
- });
-
- if (error) {
- throw error;
- }
-
- return res;
-};
-
-type DocUpdateForm = {
- name: string;
- title: string;
-};
-
-export const updateDocByName = async (token: string, name: string, form: DocUpdateForm) => {
- let error = null;
-
- const searchParams = new URLSearchParams();
- searchParams.append('name', name);
-
- const res = await fetch(`${WEBUI_API_BASE_URL}/documents/doc/update?${searchParams.toString()}`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- name: form.name,
- title: form.title
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .then((json) => {
- return json;
- })
- .catch((err) => {
- error = err.detail;
-
- console.log(err);
- return null;
- });
-
- if (error) {
- throw error;
- }
-
- return res;
-};
-
-type TagDocForm = {
- name: string;
- tags: string[];
-};
-
-export const tagDocByName = async (token: string, name: string, form: TagDocForm) => {
- let error = null;
-
- const searchParams = new URLSearchParams();
- searchParams.append('name', name);
-
- const res = await fetch(`${WEBUI_API_BASE_URL}/documents/doc/tags?${searchParams.toString()}`, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- authorization: `Bearer ${token}`
- },
- body: JSON.stringify({
- name: form.name,
- tags: form.tags
- })
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .then((json) => {
- return json;
- })
- .catch((err) => {
- error = err.detail;
-
- console.log(err);
- return null;
- });
-
- if (error) {
- throw error;
- }
-
- return res;
-};
-
-export const deleteDocByName = async (token: string, name: string) => {
- let error = null;
-
- const searchParams = new URLSearchParams();
- searchParams.append('name', name);
-
- const res = await fetch(`${WEBUI_API_BASE_URL}/documents/doc/delete?${searchParams.toString()}`, {
- method: 'DELETE',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- authorization: `Bearer ${token}`
- }
- })
- .then(async (res) => {
- if (!res.ok) throw await res.json();
- return res.json();
- })
- .then((json) => {
- return json;
- })
- .catch((err) => {
- error = err.detail;
-
- console.log(err);
- return null;
- });
-
- if (error) {
- throw error;
- }
-
- return res;
-};
diff --git a/src/lib/components/documents/AddDocModal.svelte b/src/lib/components/documents/AddDocModal.svelte
deleted file mode 100644
index 8c4d478f7..000000000
--- a/src/lib/components/documents/AddDocModal.svelte
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
-
-
-
-
{$i18n.t('Add Docs')}
-
-
-
-
-
-
-
diff --git a/src/lib/components/documents/EditDocModal.svelte b/src/lib/components/documents/EditDocModal.svelte
deleted file mode 100644
index 47577bd48..000000000
--- a/src/lib/components/documents/EditDocModal.svelte
+++ /dev/null
@@ -1,181 +0,0 @@
-
-
-
-
-
-
{$i18n.t('Edit Doc')}
-
-
-
-
-
-
-
diff --git a/src/lib/components/workspace/Documents.svelte b/src/lib/components/workspace/Documents.svelte
deleted file mode 100644
index 0fa50278c..000000000
--- a/src/lib/components/workspace/Documents.svelte
+++ /dev/null
@@ -1,627 +0,0 @@
-
-
-
-
- {$i18n.t('Documents')} | {$WEBUI_NAME}
-
-
-
-{#if dragged}
-
-{/if}
-
-{#key selectedDoc}
-
-{/key}
-
-
-
-
-
-
- {$i18n.t('Documents')}
-
-
{$documents.length}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{#if tags.length > 0}
-
-
- 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 tags as tag}
-
- {/each}
- {:else}
-
-
- {filteredDocs.filter((doc) => doc?.selected === 'checked').length} Selected
-
-
-
-
-
-
-
-
- {/if}
-
-{/if}
-
-
- {#each filteredDocs as doc}
-
- {/each}
-
-
-
- ⓘ {$i18n.t("Use '#' in the prompt input to load and select your documents.")}
-
-
-
-
-
{
- console.log(importFiles);
-
- const reader = new FileReader();
- reader.onload = async (event) => {
- const savedDocs = JSON.parse(event.target.result);
- console.log(savedDocs);
-
- for (const doc of savedDocs) {
- await createNewDoc(
- localStorage.token,
- doc.collection_name,
- doc.filename,
- doc.name,
- doc.title,
- doc.content
- ).catch((error) => {
- toast.error(error);
- return null;
- });
- }
-
- await documents.set(await getDocs(localStorage.token));
- };
-
- reader.readAsText(importFiles[0]);
- }}
- />
-
-
{
- documentsImportInputElement.click();
- }}
- >
-
- {$i18n.t('Import Documents Mapping')}
-
-
-
-
-
-
{
- let blob = new Blob([JSON.stringify($documents)], {
- type: 'application/json'
- });
- saveAs(blob, `documents-mapping-export-${Date.now()}.json`);
- }}
- >
-
- {$i18n.t('Export Documents Mapping')}
-
-
-
-
-
-
diff --git a/src/routes/(app)/admin/+layout.svelte b/src/routes/(app)/admin/+layout.svelte
index 7a2fc3c11..d3eaa3a27 100644
--- a/src/routes/(app)/admin/+layout.svelte
+++ b/src/routes/(app)/admin/+layout.svelte
@@ -67,22 +67,6 @@
: ''} transition"
href="/admin/settings">{$i18n.t('Settings')}
-
-