123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- <script lang="ts">
- import { toast } from 'svelte-sonner';
- import dayjs from 'dayjs';
- import { onMount, getContext } from 'svelte';
- import { createNewDoc, getDocs, tagDocByName, updateDocByName } from '$lib/apis/documents';
- import Modal from '../common/Modal.svelte';
- import { documents } from '$lib/stores';
- import TagInput from '../common/Tags/TagInput.svelte';
- import Tags from '../common/Tags.svelte';
- import { addTagById } from '$lib/apis/chats';
- import { uploadDocToVectorDB } from '$lib/apis/rag';
- import { transformFileName } from '$lib/utils';
- import { SUPPORTED_FILE_EXTENSIONS, SUPPORTED_FILE_TYPE } from '$lib/constants';
- const i18n = getContext('i18n');
- export let show = false;
- let uploadDocInputElement: HTMLInputElement;
- let inputFiles;
- let tags = [];
- let doc = {
- name: '',
- title: '',
- content: null
- };
- const uploadDoc = async (file) => {
- const res = await uploadDocToVectorDB(localStorage.token, '', file).catch((error) => {
- toast.error(error);
- return null;
- });
- if (res) {
- await createNewDoc(
- localStorage.token,
- res.collection_name,
- res.filename,
- transformFileName(res.filename),
- res.filename,
- tags.length > 0
- ? {
- tags: tags
- }
- : null
- ).catch((error) => {
- toast.error(error);
- return null;
- });
- await documents.set(await getDocs(localStorage.token));
- }
- };
- const submitHandler = async () => {
- 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;
- uploadDocInputElement.value = '';
- } else {
- toast.error($i18n.t(`File not found.`));
- }
- show = false;
- documents.set(await getDocs(localStorage.token));
- };
- const addTagHandler = async (tagName) => {
- if (!tags.find((tag) => tag.name === tagName) && tagName !== '') {
- tags = [...tags, { name: tagName }];
- } else {
- console.log('tag already exists');
- }
- };
- const deleteTagHandler = async (tagName) => {
- tags = tags.filter((tag) => tag.name !== tagName);
- };
- onMount(() => {});
- </script>
- <Modal size="sm" bind:show>
- <div>
- <div class=" flex justify-between dark:text-gray-300 px-5 py-4">
- <div class=" text-lg font-medium self-center">{$i18n.t('Add Docs')}</div>
- <button
- class="self-center"
- on:click={() => {
- show = false;
- }}
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 20 20"
- fill="currentColor"
- class="w-5 h-5"
- >
- <path
- d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
- />
- </svg>
- </button>
- </div>
- <hr class=" dark:border-gray-800" />
- <div class="flex flex-col md:flex-row w-full px-5 py-4 md:space-x-4 dark:text-gray-200">
- <div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
- <form
- class="flex flex-col w-full"
- on:submit|preventDefault={() => {
- submitHandler();
- }}
- >
- <div class="mb-3 w-full">
- <input
- id="upload-doc-input"
- bind:this={uploadDocInputElement}
- hidden
- bind:files={inputFiles}
- type="file"
- multiple
- />
- <button
- class="w-full text-sm font-medium py-3 bg-gray-100 hover:bg-gray-200 dark:bg-gray-850 dark:hover:bg-gray-800 text-center rounded-xl"
- type="button"
- on:click={() => {
- uploadDocInputElement.click();
- }}
- >
- {#if inputFiles}
- {inputFiles.length > 0 ? `${inputFiles.length}` : ''} document(s) selected.
- {:else}
- {$i18n.t('Click here to select documents.')}
- {/if}
- </button>
- </div>
- <div class=" flex flex-col space-y-1.5">
- <div class="flex flex-col w-full">
- <div class=" mb-1.5 text-xs text-gray-500">{$i18n.t('Tags')}</div>
- <Tags {tags} addTag={addTagHandler} deleteTag={deleteTagHandler} />
- </div>
- </div>
- <div class="flex justify-end pt-5 text-sm font-medium">
- <button
- class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded"
- type="submit"
- >
- {$i18n.t('Save')}
- </button>
- </div>
- </form>
- </div>
- </div>
- </div>
- </Modal>
- <style>
- input::-webkit-outer-spin-button,
- input::-webkit-inner-spin-button {
- /* display: none; <- Crashes Chrome on hover */
- -webkit-appearance: none;
- margin: 0; /* <-- Apparently some margin are still there even though it's hidden */
- }
- .tabs::-webkit-scrollbar {
- display: none; /* for Chrome, Safari and Opera */
- }
- .tabs {
- -ms-overflow-style: none; /* IE and Edge */
- scrollbar-width: none; /* Firefox */
- }
- input[type='number'] {
- -moz-appearance: textfield; /* Firefox */
- }
- </style>
|