diff --git a/src/lib/components/common/RichTextInput.svelte b/src/lib/components/common/RichTextInput.svelte
index fa35add42..326b033b2 100644
--- a/src/lib/components/common/RichTextInput.svelte
+++ b/src/lib/components/common/RichTextInput.svelte
@@ -165,6 +165,10 @@
// Usage example
content = await tryParse(value);
}
+ } else {
+ if (html && !content) {
+ content = html;
+ }
}
console.log('content', content);
diff --git a/src/lib/components/notes/NoteEditor.svelte b/src/lib/components/notes/NoteEditor.svelte
index c247f6909..36651d2a0 100644
--- a/src/lib/components/notes/NoteEditor.svelte
+++ b/src/lib/components/notes/NoteEditor.svelte
@@ -504,6 +504,7 @@
className="input-prose-sm px-0.5"
bind:value={note.data.content.json}
placeholder={$i18n.t('Write something...')}
+ html={note.data?.content?.html}
json={true}
onChange={(content) => {
note.data.content.html = content.html;
diff --git a/src/lib/components/notes/Notes.svelte b/src/lib/components/notes/Notes.svelte
index 7ec9d830e..932b5a670 100644
--- a/src/lib/components/notes/Notes.svelte
+++ b/src/lib/components/notes/Notes.svelte
@@ -28,7 +28,7 @@
$: loadLocale($i18n.languages);
import { goto } from '$app/navigation';
- import { onMount, getContext } from 'svelte';
+ import { onMount, getContext, onDestroy } from 'svelte';
import { WEBUI_NAME, config, prompts as _prompts, user } from '$lib/stores';
import { createNewNote, deleteNoteById, getNotes } from '$lib/apis/notes';
@@ -42,6 +42,8 @@
import Spinner from '../common/Spinner.svelte';
import Tooltip from '../common/Tooltip.svelte';
import NoteMenu from './Notes/NoteMenu.svelte';
+ import FilesOverlay from '../chat/MessageInput/FilesOverlay.svelte';
+ import { marked } from 'marked';
const i18n = getContext('i18n');
let loaded = false;
@@ -166,9 +168,103 @@
}
};
+ const inputFilesHandler = async (inputFiles) => {
+ // Check if all the file is a markdown file and extract name and content
+
+ for (const file of inputFiles) {
+ if (file.type !== 'text/markdown') {
+ toast.error($i18n.t('Only markdown files are allowed'));
+ return;
+ }
+
+ const reader = new FileReader();
+ reader.onload = async (event) => {
+ const content = event.target.result;
+ let name = file.name.replace(/\.md$/, '');
+
+ if (typeof content !== 'string') {
+ toast.error($i18n.t('Invalid file content'));
+ return;
+ }
+
+ // Create a new note with the content
+ const res = await createNewNote(localStorage.token, {
+ title: name,
+ data: {
+ content: {
+ json: null,
+ html: marked.parse(content ?? ''),
+ md: content
+ }
+ },
+ meta: null,
+ access_control: null
+ }).catch((error) => {
+ toast.error(`${error}`);
+ return null;
+ });
+
+ if (res) {
+ init();
+ }
+ };
+
+ reader.readAsText(file);
+ }
+ };
+
+ let dragged = false;
+
+ const onDragOver = (e) => {
+ e.preventDefault();
+
+ // Check if a file is being dragged.
+ if (e.dataTransfer?.types?.includes('Files')) {
+ dragged = true;
+ } else {
+ dragged = false;
+ }
+ };
+
+ const onDragLeave = () => {
+ dragged = false;
+ };
+
+ const onDrop = async (e) => {
+ e.preventDefault();
+ console.log(e);
+
+ if (e.dataTransfer?.files) {
+ const inputFiles = Array.from(e.dataTransfer?.files);
+ if (inputFiles && inputFiles.length > 0) {
+ console.log(inputFiles);
+ inputFilesHandler(inputFiles);
+ }
+ }
+
+ dragged = false;
+ };
+
+ onDestroy(() => {
+ console.log('destroy');
+ const dropzoneElement = document.getElementById('notes-container');
+
+ if (dropzoneElement) {
+ dropzoneElement?.removeEventListener('dragover', onDragOver);
+ dropzoneElement?.removeEventListener('drop', onDrop);
+ dropzoneElement?.removeEventListener('dragleave', onDragLeave);
+ }
+ });
+
onMount(async () => {
await init();
loaded = true;
+
+ const dropzoneElement = document.getElementById('notes-container');
+
+ dropzoneElement?.addEventListener('dragover', onDragOver);
+ dropzoneElement?.addEventListener('drop', onDrop);
+ dropzoneElement?.addEventListener('dragleave', onDragLeave);
});
@@ -178,136 +274,139 @@
-{#if loaded}
-