mirror of
https://github.com/geoffsee/open-gsio.git
synced 2025-09-08 22:56:46 +00:00
Remove file upload functionality and related components
The `FileUploadStore` and all file upload features were removed, simplifying the chat interface. This change eliminates unused code, including file handling logic, attachment management, and UI elements, streamlining the application.
This commit is contained in:

committed by
Geoff Seemueller

parent
18ba4aec21
commit
c04e19611e
@@ -1,15 +1,6 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import {
|
||||
Alert,
|
||||
AlertIcon,
|
||||
Box,
|
||||
chakra,
|
||||
HStack,
|
||||
InputGroup,
|
||||
} from "@chakra-ui/react";
|
||||
import fileUploadStore from "../../stores/FileUploadStore";
|
||||
import { UploadedItem } from "./Attachments";
|
||||
import React, {useEffect, useRef, useState} from "react";
|
||||
import {observer} from "mobx-react-lite";
|
||||
import {Box, chakra, InputGroup,} from "@chakra-ui/react";
|
||||
import AutoResize from "react-textarea-autosize";
|
||||
|
||||
const AutoResizeTextArea = chakra(AutoResize);
|
||||
@@ -24,24 +15,6 @@ interface InputTextAreaProps {
|
||||
|
||||
const InputTextArea: React.FC<InputTextAreaProps> = observer(
|
||||
({ inputRef, value, onChange, onKeyDown, isLoading }) => {
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleAttachmentClick = () => {
|
||||
if (fileInputRef.current) {
|
||||
fileInputRef.current.click();
|
||||
}
|
||||
};
|
||||
|
||||
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = event.target.files?.[0];
|
||||
if (file) {
|
||||
fileUploadStore.uploadFile(file, "/api/documents");
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoveUploadedItem = (url: string) => {
|
||||
fileUploadStore.removeUploadedFile(url);
|
||||
};
|
||||
|
||||
const [heightConstraint, setHeightConstraint] = useState<
|
||||
number | undefined
|
||||
@@ -61,26 +34,6 @@ const InputTextArea: React.FC<InputTextAreaProps> = observer(
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
>
|
||||
{/* Attachments Section */}
|
||||
{fileUploadStore.uploadResults.length > 0 && (
|
||||
<HStack
|
||||
spacing={2}
|
||||
mb={2}
|
||||
overflowX="auto"
|
||||
css={{ "&::-webkit-scrollbar": { display: "none" } }}
|
||||
// Ensure attachments wrap if needed
|
||||
flexWrap="wrap"
|
||||
>
|
||||
{fileUploadStore.uploadResults.map((result) => (
|
||||
<UploadedItem
|
||||
key={result.url}
|
||||
url={result.url}
|
||||
name={result.name}
|
||||
onRemove={() => handleRemoveUploadedItem(result.url)}
|
||||
/>
|
||||
))}
|
||||
</HStack>
|
||||
)}
|
||||
|
||||
{/* Input Area */}
|
||||
<InputGroup position="relative">
|
||||
@@ -97,7 +50,7 @@ const InputTextArea: React.FC<InputTextAreaProps> = observer(
|
||||
pl="17px"
|
||||
bg="rgba(255, 255, 255, 0.15)"
|
||||
color="text.primary"
|
||||
borderRadius="20px" // Set a consistent border radius
|
||||
borderRadius="20px"
|
||||
border="none"
|
||||
placeholder="Free my mind..."
|
||||
_placeholder={{ color: "gray.400" }}
|
||||
@@ -115,32 +68,7 @@ const InputTextArea: React.FC<InputTextAreaProps> = observer(
|
||||
transition: "height 0.2s ease-in-out",
|
||||
}}
|
||||
/>
|
||||
{/*<InputRightElement*/}
|
||||
{/* position="absolute"*/}
|
||||
{/* right={0}*/}
|
||||
{/* top={0}*/}
|
||||
{/* bottom={0}*/}
|
||||
{/* width="40px"*/}
|
||||
{/* height="100%"*/}
|
||||
{/* display="flex"*/}
|
||||
{/* alignItems="center"*/}
|
||||
{/* justifyContent="center"*/}
|
||||
{/*>*/}
|
||||
{/*<EnableSearchButton />*/}
|
||||
{/*</InputRightElement>*/}
|
||||
</InputGroup>
|
||||
<input
|
||||
type="file"
|
||||
ref={fileInputRef}
|
||||
style={{ display: "none" }}
|
||||
onChange={handleFileChange}
|
||||
/>
|
||||
{fileUploadStore.uploadError && (
|
||||
<Alert status="error" mt={2}>
|
||||
<AlertIcon />
|
||||
{fileUploadStore.uploadError}
|
||||
</Alert>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
},
|
||||
|
@@ -1,3 +1,4 @@
|
||||
// runs before anything else
|
||||
import UserOptionsStore from "../stores/UserOptionsStore";
|
||||
|
||||
UserOptionsStore.initialize();
|
||||
|
@@ -1,10 +1,10 @@
|
||||
// https://vike.dev/data
|
||||
import Routes from "../../src/renderer/routes";
|
||||
|
||||
export { data };
|
||||
export type Data = Awaited<ReturnType<typeof data>>;
|
||||
import type { PageContextServer } from "vike/types";
|
||||
|
||||
// sets the window title depending on the route
|
||||
const data = async (pageContext: PageContextServer) => {
|
||||
const getTitle = (path) => {
|
||||
return Routes[normalizePath(path)]?.heroLabel || "";
|
||||
|
@@ -1,3 +1,4 @@
|
||||
// client error catcher
|
||||
import { usePageContext } from "../../renderer/usePageContext";
|
||||
import { Center, Text } from "@chakra-ui/react";
|
||||
|
||||
|
@@ -4,7 +4,7 @@ import Chat from "../../components/chat/Chat";
|
||||
import clientChatStore from "../../stores/ClientChatStore";
|
||||
import { getModelFamily } from "../../components/chat/SupportedModels";
|
||||
|
||||
// renders for path: "/"
|
||||
// renders "/"
|
||||
export default function IndexPage() {
|
||||
useEffect(() => {
|
||||
try {
|
||||
|
@@ -1,10 +1,10 @@
|
||||
// https://vike.dev/onRenderClient
|
||||
export { onRenderClient };
|
||||
|
||||
import React from "react";
|
||||
import { hydrateRoot } from "react-dom/client";
|
||||
import { Layout } from "../layout/Layout";
|
||||
|
||||
// See https://vike.dev/onRenderClient for usage details
|
||||
async function onRenderClient(pageContext) {
|
||||
const { Page, pageProps } = pageContext;
|
||||
hydrateRoot(
|
||||
@@ -13,4 +13,4 @@ async function onRenderClient(pageContext) {
|
||||
<Page {...pageProps} />
|
||||
</Layout>,
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,5 +1,4 @@
|
||||
import React from "react";
|
||||
// https://vike.dev/onRenderHtml
|
||||
export { onRenderHtml };
|
||||
|
||||
import { renderToStream } from "react-streaming/server";
|
||||
@@ -7,6 +6,7 @@ import { escapeInject } from "vike/server";
|
||||
import { Layout } from "../layout/Layout";
|
||||
import type { OnRenderHtmlAsync } from "vike/types";
|
||||
|
||||
// See https://vike.dev/onRenderHtml for usage details
|
||||
const onRenderHtml: OnRenderHtmlAsync = async (
|
||||
pageContext,
|
||||
): ReturnType<OnRenderHtmlAsync> => {
|
||||
@@ -49,8 +49,6 @@ window.ga_api = "/api/metrics";
|
||||
|
||||
return {
|
||||
documentHtml: res,
|
||||
pageContext: {
|
||||
// enableEagerStreaming: true
|
||||
},
|
||||
pageContext: {},
|
||||
};
|
||||
};
|
||||
|
@@ -1,3 +1,4 @@
|
||||
// Top level control interface for navigation
|
||||
export default {
|
||||
"/": { sidebarLabel: "Home", heroLabel: "g.s" },
|
||||
// "/about": { sidebarLabel: "About", heroLabel: "About Me" },
|
||||
|
@@ -1,4 +1,3 @@
|
||||
// renderer/types.ts
|
||||
export type { PageProps };
|
||||
|
||||
type Page = (pageProps: PageProps) => React.ReactElement;
|
||||
@@ -10,8 +9,6 @@ declare global {
|
||||
Page: Page;
|
||||
pageProps?: PageProps;
|
||||
fetch?: typeof fetch;
|
||||
|
||||
// Add your environment bindings here
|
||||
env: import("../../workers/site/env");
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import { applySnapshot, flow, Instance, types } from "mobx-state-tree";
|
||||
import Message from "../models/Message";
|
||||
import Attachment from "../models/Attachment";
|
||||
import IntermediateStep from "../models/IntermediateStep";
|
||||
import UserOptionsStore from "./UserOptionsStore";
|
||||
|
||||
@@ -11,7 +10,6 @@ const ClientChatStore = types
|
||||
isLoading: types.optional(types.boolean, false),
|
||||
model: types.optional(types.string, "llama-3.3-70b-versatile"),
|
||||
imageModel: types.optional(types.string, "black-forest-labs/flux-1.1-pro"),
|
||||
attachments: types.optional(types.array(Attachment), []),
|
||||
tools: types.optional(types.array(types.string), []),
|
||||
intermediateSteps: types.array(IntermediateStep),
|
||||
})
|
||||
@@ -41,7 +39,6 @@ const ClientChatStore = types
|
||||
const payload = {
|
||||
messages: self.messages.slice(),
|
||||
model: self.model,
|
||||
attachments: self.attachments.slice(),
|
||||
tools: self.tools.slice(),
|
||||
};
|
||||
|
||||
@@ -163,7 +160,6 @@ const ClientChatStore = types
|
||||
const payload = {
|
||||
messages: self.messages.slice(),
|
||||
model: self.model,
|
||||
attachments: self.attachments.slice(),
|
||||
tools: self.tools.slice(),
|
||||
};
|
||||
|
||||
@@ -244,15 +240,6 @@ const ClientChatStore = types
|
||||
reset() {
|
||||
applySnapshot(self, {});
|
||||
},
|
||||
addAttachment(attachment: Instance<typeof Attachment>) {
|
||||
self.attachments.push(attachment);
|
||||
|
||||
if (self.attachments.length > 0) {
|
||||
if (!self.tools.includes("user-attachments")) {
|
||||
self.tools.push("user-attachments");
|
||||
}
|
||||
}
|
||||
},
|
||||
addIntermediateStep(stepData) {
|
||||
return;
|
||||
},
|
||||
@@ -271,21 +258,6 @@ const ClientChatStore = types
|
||||
self.messages.splice(index + 1);
|
||||
}
|
||||
},
|
||||
removeAttachment(url: string) {
|
||||
const f =
|
||||
self.attachments.filter((attachment) => attachment.url !== url) ?? [];
|
||||
self.attachments.clear();
|
||||
|
||||
self.attachments.push(...f);
|
||||
|
||||
if (self.attachments.length === 0) {
|
||||
const remainingTools = self.tools.filter(
|
||||
(tool) => tool !== "user-attachments",
|
||||
);
|
||||
self.tools.clear();
|
||||
self.tools.push(...remainingTools);
|
||||
}
|
||||
},
|
||||
setTools(tools: string[]) {
|
||||
self.tools.clear();
|
||||
self.tools.push(...tools);
|
||||
|
@@ -1,67 +0,0 @@
|
||||
import { types, flow } from "mobx-state-tree";
|
||||
import clientChatStore from "./ClientChatStore";
|
||||
import Attachment from "../models/Attachment";
|
||||
|
||||
const FileUploadStore = types
|
||||
.model("FileUploadStore", {
|
||||
isUploading: types.optional(types.boolean, false),
|
||||
uploadError: types.maybeNull(types.string),
|
||||
uploadedFiles: types.array(types.string),
|
||||
uploadResults: types.array(types.frozen()),
|
||||
})
|
||||
.actions((self) => ({
|
||||
uploadFile: flow(function* (file: File, endpoint: string) {
|
||||
if (!endpoint) {
|
||||
self.uploadError = "Endpoint URL is required.";
|
||||
return;
|
||||
}
|
||||
|
||||
self.isUploading = true;
|
||||
self.uploadError = null;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
try {
|
||||
const response = yield fetch(endpoint, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Upload failed with status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = yield response.json();
|
||||
self.uploadResults.push(result);
|
||||
|
||||
if (result.url) {
|
||||
self.uploadedFiles.push(result.url);
|
||||
clientChatStore.addAttachment(
|
||||
Attachment.create({
|
||||
content: `${file.name}\n~~~${result?.extractedText}\n`,
|
||||
url: result.url,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
throw new Error("No URL returned from the server.");
|
||||
}
|
||||
} catch (error: any) {
|
||||
self.uploadError = error.message;
|
||||
} finally {
|
||||
self.isUploading = false;
|
||||
}
|
||||
}),
|
||||
removeUploadedFile(url: string) {
|
||||
clientChatStore.removeAttachment(url);
|
||||
const index = self.uploadedFiles.findIndex(
|
||||
(uploadedUrl) => uploadedUrl === url,
|
||||
);
|
||||
if (index !== -1) {
|
||||
self.uploadedFiles.splice(index, 1);
|
||||
self.uploadResults.splice(index, 1);
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
export default FileUploadStore.create();
|
Reference in New Issue
Block a user