diff --git a/package-lock.json b/package-lock.json index cd7e6de0d..c490d0e94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,6 +71,7 @@ "react-dom": "^18.2.0", "react-dropzone": "^14.2.10", "react-markdown": "^9.0.1", + "react-router": "^7.1.5", "react-syntax-highlighter": "^15.5.0", "redux-persist": "^6.0.0", "rehype-katex": "^7.0.0", @@ -20211,6 +20212,39 @@ } } }, + "node_modules/react-router": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.5.tgz", + "integrity": "sha512-8BUF+hZEU4/z/JD201yK6S+UYhsf58bzYIDq2NS1iGpwxSXDu7F+DeGSkIXMFBuHZB21FSiCzEcUb18cQNdRkA==", + "dev": true, + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -21209,6 +21243,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "dev": true + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -22335,6 +22375,12 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", + "dev": true + }, "node_modules/tween-functions": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", diff --git a/package.json b/package.json index 9ef5f0c82..fde88c137 100644 --- a/package.json +++ b/package.json @@ -109,6 +109,7 @@ "react-dom": "^18.2.0", "react-dropzone": "^14.2.10", "react-markdown": "^9.0.1", + "react-router": "^7.1.5", "react-syntax-highlighter": "^15.5.0", "redux-persist": "^6.0.0", "rehype-katex": "^7.0.0", diff --git a/src/components/Chat/Chat.tsx b/src/components/Chat/Chat.tsx index 5f411bd69..bccdc2a26 100644 --- a/src/components/Chat/Chat.tsx +++ b/src/components/Chat/Chat.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useEffect, useState } from "react"; -import { ChatForm, ChatFormProps } from "../ChatForm"; +import { ChatForm } from "../ChatForm"; import { ChatContent } from "../ChatContent"; import { Flex, Button, Text, Card } from "@radix-ui/themes"; import { @@ -36,14 +36,9 @@ export type ChatProps = { backFromChat: () => void; style?: React.CSSProperties; unCalledTools: boolean; - maybeSendToSidebar: ChatFormProps["onClose"]; }; -export const Chat: React.FC = ({ - style, - unCalledTools, - maybeSendToSidebar, -}) => { +export const Chat: React.FC = ({ style, unCalledTools }) => { const dispatch = useAppDispatch(); const [isViewingRawJSON, setIsViewingRawJSON] = useState(false); @@ -142,7 +137,6 @@ export const Chat: React.FC = ({ diff --git a/src/components/ChatForm/ChatForm.tsx b/src/components/ChatForm/ChatForm.tsx index 56c3c3bd2..8166bcdc9 100644 --- a/src/components/ChatForm/ChatForm.tsx +++ b/src/components/ChatForm/ChatForm.tsx @@ -3,11 +3,7 @@ import React, { useCallback, useEffect, useMemo } from "react"; import { Flex, Card, Text } from "@radix-ui/themes"; import styles from "./ChatForm.module.css"; -import { - PaperPlaneButton, - BackToSideBarButton, - AgentIntegrationsButton, -} from "../Buttons/Buttons"; +import { PaperPlaneButton, AgentIntegrationsButton } from "../Buttons/Buttons"; import { TextArea } from "../TextArea"; import { Form } from "./Form"; import { @@ -57,14 +53,13 @@ import { AgentCapabilities } from "./AgentCapabilities"; export type ChatFormProps = { onSubmit: (str: string) => void; - onClose?: () => void; className?: string; unCalledTools: boolean; }; export const ChatForm: React.FC = ({ onSubmit, - onClose, + className, unCalledTools, }) => { @@ -362,14 +357,6 @@ export const ChatForm: React.FC = ({ ref={(x) => refs.setSetupIntegrations(x)} /> )} - {onClose && ( - - )} {config.features?.images !== false && isMultimodalitySupportedForCurrentModel && } {/* TODO: Reserved space for microphone button coming later on */} diff --git a/src/components/ChatHistory/ChatHistory.tsx b/src/components/ChatHistory/ChatHistory.tsx index dbd273cc7..c2d129309 100644 --- a/src/components/ChatHistory/ChatHistory.tsx +++ b/src/components/ChatHistory/ChatHistory.tsx @@ -6,25 +6,26 @@ import { getHistory, type HistoryState, } from "../../features/History/historySlice"; -import type { ChatThread } from "../../features/Chat/Thread/types"; +// import type { ChatThread } from "../../features/Chat/Thread/types"; export type ChatHistoryProps = { history: HistoryState; - onHistoryItemClick: (id: ChatThread) => void; + // onHistoryItemClick: (id: ChatThread) => void; onDeleteHistoryItem: (id: string) => void; onOpenChatInTab?: (id: string) => void; currentChatId?: string; }; - +// TODO: history item should be a nav link export const ChatHistory = memo( ({ history, - onHistoryItemClick, + // onHistoryItemClick, onDeleteHistoryItem, onOpenChatInTab, currentChatId, }: ChatHistoryProps) => { const sortedHistory = getHistory({ history }); + return ( {sortedHistory.map((item) => ( onHistoryItemClick(item)} + // onClick={() => onHistoryItemClick(item)} onOpenInTab={onOpenChatInTab} onDelete={onDeleteHistoryItem} key={item.id} diff --git a/src/components/ChatHistory/HistoryItem.tsx b/src/components/ChatHistory/HistoryItem.tsx index f3c079575..063d0e65d 100644 --- a/src/components/ChatHistory/HistoryItem.tsx +++ b/src/components/ChatHistory/HistoryItem.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useCallback } from "react"; import { Card, Flex, Text, Box, Spinner } from "@radix-ui/themes"; // import type { ChatHistoryItem } from "../../hooks/useChatHistory"; import { ChatBubbleIcon, DotFilledIcon } from "@radix-ui/react-icons"; @@ -8,17 +8,34 @@ import { OpenInNewWindowIcon } from "@radix-ui/react-icons"; import type { ChatHistoryItem } from "../../features/History/historySlice"; import { isUserMessage } from "../../services/refact"; import { useAppSelector } from "../../hooks"; +import { useNavigate } from "react-router"; export const HistoryItem: React.FC<{ historyItem: ChatHistoryItem; - onClick: () => void; + // onClick: () => void; onDelete: (id: string) => void; onOpenInTab?: (id: string) => void; disabled: boolean; -}> = ({ historyItem, onClick, onDelete, onOpenInTab, disabled }) => { +}> = ({ + historyItem, + // onClick, + onDelete, + onOpenInTab, + disabled, +}) => { const dateCreated = new Date(historyItem.createdAt); const dateTimeString = dateCreated.toLocaleString(); const cache = useAppSelector((app) => app.chat.cache); + const navigate = useNavigate(); + + const handleClick = useCallback( + (event: React.MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); + void navigate(`/chat/${historyItem.id}`); + }, + [historyItem.id, navigate], + ); const isStreaming = historyItem.id in cache; return ( @@ -34,14 +51,7 @@ export const HistoryItem: React.FC<{ asChild role="button" > -