mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-03 05:29:12 +00:00
Add support for converting an attached doc and chatting with it
- Document is first converted in the chatinputarea, then sent to the chat component. From there, it's sent in the chat API body and then processed by the backend - We couldn't directly use a UploadFile type in the backend API because we'd have to convert the api type to a multipart form. This would require other client side migrations without uniform benefit, which is why we do it in this two-phase process. This also gives us capacity to repurpose the moe generic interface down the road.
This commit is contained in:
@@ -267,6 +267,58 @@ export async function createNewConversation(slug: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function packageFilesForUpload(files: FileList): Promise<FormData> {
|
||||
const formData = new FormData();
|
||||
|
||||
const fileReadPromises = Array.from(files).map((file) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
let reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
if (event.target === null) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
let fileContents = event.target.result;
|
||||
let fileType = file.type;
|
||||
let fileName = file.name;
|
||||
if (fileType === "") {
|
||||
let fileExtension = fileName.split(".").pop();
|
||||
if (fileExtension === "org") {
|
||||
fileType = "text/org";
|
||||
} else if (fileExtension === "md") {
|
||||
fileType = "text/markdown";
|
||||
} else if (fileExtension === "txt") {
|
||||
fileType = "text/plain";
|
||||
} else if (fileExtension === "html") {
|
||||
fileType = "text/html";
|
||||
} else if (fileExtension === "pdf") {
|
||||
fileType = "application/pdf";
|
||||
} else {
|
||||
// Skip this file if its type is not supported
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileContents === null) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
let fileObj = new Blob([fileContents], { type: fileType });
|
||||
formData.append("files", fileObj, file.name);
|
||||
resolve();
|
||||
};
|
||||
reader.onerror = reject;
|
||||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
});
|
||||
|
||||
await Promise.all(fileReadPromises);
|
||||
return formData;
|
||||
}
|
||||
|
||||
export function uploadDataForIndexing(
|
||||
files: FileList,
|
||||
setWarning: (warning: string) => void,
|
||||
|
||||
@@ -71,6 +71,16 @@ export function useIsMobileWidth() {
|
||||
return isMobileWidth;
|
||||
}
|
||||
|
||||
export const convertBytesToText = (fileSize: number) => {
|
||||
if (fileSize < 1024) {
|
||||
return `${fileSize} B`;
|
||||
} else if (fileSize < 1024 * 1024) {
|
||||
return `${(fileSize / 1024).toFixed(2)} KB`;
|
||||
} else {
|
||||
return `${(fileSize / (1024 * 1024)).toFixed(2)} MB`;
|
||||
}
|
||||
};
|
||||
|
||||
export function useDebounce<T>(value: T, delay: number): T {
|
||||
const [debouncedValue, setDebouncedValue] = useState<T>(value);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user